linuxカーネルの水はとても深くて、分かち合います__についてraw_writel()エラーの問題


まず、前のテストコードで説明します.
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/io.h>

#define at91_pwm_read(reg)                  __raw_readl(reg)   
#define at91_pwm_write(reg, val)            __raw_writel((val), reg)

#define PWMC_BASE 0xfffb8000
#define PWM_MR_OFF              0x00000000    ///< PWM Mode Register offset.
//#define PWM_MR     __phys_to_pfn(PWMC_BASE + PWM_MR_OFF) ///< PWM Mode Register.  //     
#define PWM_MR     (PWMC_BASE + PWM_MR_OFF) ///< PWM Mode Register.

static int __init my_led_init(void)
{
	unsigned long value;
	

	
	value = at91_pwm_read(PWM_MR);
	printk("0xfffb8000 = %x", value);
	at91_pwm_write(PWM_MR, 0xA2); 
	value = at91_pwm_read(PWM_MR);
	printk("0xfffb8000 = %x", value);
	
	at91_set_gpio_output(AT91_PIN_PD15, 0);
	at91_set_gpio_value(AT91_PIN_PD15, 0);
    return 0;
}
static void __exit my_led_exit(void)
{
   
	//at91_set_gpio_output(AT91_PIN_PD15, 0);
	at91_set_gpio_value(AT91_PIN_PD15, 1);

    return;
}

module_init(my_led_init)
module_exit(my_led_exit)

MODULE_LICENSE("GPL");

実はこれは簡単なロードとアンインストール駆動のモジュールです.昨日作ったpwmの駆動が開発ボードにダウンロードされたとき、いつもエラーを報告していたので、コードの中で長い間原因を見つけられませんでした.
今朝モジュールを単独で出してみましたが、最後に確定しました.raw_writelと_raw_readlの原因は、私が定義したアドレスが間違っていると思っていたからです.その後、長い間デバッグしたが、見つからなかった.前のエラーの情報;
<1>Unable to handle kernel paging request at virtual address fffb8000
pgd = c6c14000
[fffb8000] *pgd=705a5031, *pte=00000000, *ppte=00000000
Internal error: Oops: 17 [#1]
Modules linked in: myled(+) [last unloaded: myled]
CPU: 0    Not tainted  (2.6.30 #28)
PC is at my_led_init+0x10/0x58 [myled]
LR is at do_one_initcall+0x4c/0x17c
pc : [<bf00f010>]    lr : [<c01222d4>]    psr: 60000013
sp : c6c2df08  ip : 00000000  fp : bec68c94
r10: 00000000  r9 : c6c2c000  r8 : c0483140
r7 : bf00f000  r6 : 001e5060  r5 : bf00c01c  r4 : fffb8fff
r3 : 00000000  r2 : c6c2c000  r1 : 00000001  r0 : bf00f000
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 0005317f  Table: 76c14000  DAC: 00000015
Process insmod (pid: 450, stack limit = 0xc6c2c268)
Stack: (0xc6c2df08 to 0xc6c2e000)
df00:                   00000000 00000ae4 bf00c320 c01222d4 c888e2ce c79cf420 
df20: c888ea10 00000016 00000018 c888e3d0 bf00c32c c888e768 c6c14000 00000000 
df40: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
df60: 00000ae4 bf00c320 001e5060 00000ae4 bf00c320 001e5060 00000000 c0122ea8 
df80: 00000000 c0157f24 c7815740 ffffffff 001e44c0 00000ae4 bec68db1 000002ec 
dfa0: 00000080 c0122d00 00000ae4 bec68db1 001e5060 00000ae4 001e5050 bec68db1 
dfc0: 00000ae4 bec68db1 000002ec 00000080 00000000 00000002 00000000 bec68c94 
dfe0: bec68ab8 bec68aa8 0002cdbc 00009300 20000010 001e5060 00000000 00000000 
[<bf00f010>] (my_led_init+0x10/0x58 [myled]) from [<c01222d4>] (do_one_initcall+0x4c/0x17c)
[<c01222d4>] (do_one_initcall+0x4c/0x17c) from [<c0157f24>] (sys_init_module+0x90/0x194)
[<c0157f24>] (sys_init_module+0x90/0x194) from [<c0122d00>] (ret_fast_syscall+0x0/0x2c)
Code: e92d4030 e59f5048 e3e04a47 e24dd004 (e5141fff) 
---[ end trace 55d98dffd0e5be81 ]---
Segmentation fault

ありがとう
Crack-Punk
http://blog.chinaunix.net/uid-27039867-id-3236478.html
先人が木を植え、後人が涼む.貴さんの内容を空間に転載します.
          ,          ,     ...
                     ,   ,      。     Linux 2.6.19.2,       (  ,2.6.17   ),      ,        。   include/asm-arm/irq.h       irq      , :
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.c ^_^ google    pathch-cs89x0 ,     ...    patch   2.6.14,  patch  ,            、       ,      。  ,          ,           oops:
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)
 <0>Kernel panic - not syncing: Attempted to kill init!
           《Linux       》        ,           ...      Linux          。          ,  。           ,google          ARM Linux Kernel Porting ,    , cs8900     0x19000000   (    A24        cs8900  , +1000000),     ,          ,       ,          cs89x0  (         ^_^)。    ,             ...
            ,       ,      ,               smdk2410_iodesc      。          unsigned long physical    unsigned long pfn 。   smdk2410_iodesc    SMDK2410_PA_CS8900A_BASE       physical  ,     Unable to handle kernel paging request   。     http://bibu.blogchina.com/bibu/4914641.html   ,    ,            Ok  ^_^
#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 
  
int set_irq_type(unsigned int irq, unsigned int type);
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 @@
   Dmitry Pervushin  : [email protected]
                     : PNX010X platform support
 
+  Christian Pell    : [email protected]
+                    : 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 <linux/irq.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/smdk2410-map.h>
+
+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
+#endif
+#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<<2))|(0x2<<2),S3C2410_GPGCON);
+ __raw_writel((__raw_readl(S3C2410_EXTINT1)&~(0x7<<4))|(0x4<<4),S3C2410_EXTINT1);
+#endif
  if (net_debug)
   printk("cs89x0:cs89x0_probe(0x%x)
", io); @@ -386,6 +414,18 @@ { outw(value, base_addr + (portno << 1)); } +#elif defined(CONFIG_ARCH_S3C2410) //Added weibing +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); +} #else 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) struct net_local *lp = netdev_priv(dev); - 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 < 2) { /* Allow interrupts to be generated by the chip */ /* Cirrus' release had this: */ @@ -1309,7 +1360,7 @@ else #endif { -#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 << dev->irq) & lp->irq_map) == 0) { printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x
", dev->name, dev->irq, lp->irq_map); @@ -1324,6 +1375,9 @@ writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON); #endif write_irq(dev, lp->chip_type, dev->irq); +#if defined(CONFIG_ARCH_S3C2410) + set_irq_type(dev->irq, IRQT_RISING); +#endif 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; #endif 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; - int ioaddr = dev->base_addr; + unsigned int ioaddr = dev->base_addr; status = readword(ioaddr, RX_FRAME_PORT); length = readword(ioaddr, RX_FRAME_PORT); 5. , , happy... , NFS , ... ...... ...... , , io ,request_region(0xf4000300, 0x10) failed 。 cs89x0:cs89x0_probe(0x0) 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:cs89x0_probe(0x0) 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 ... , , ... 443 for (;;) { 444 struct resource *conflict; 445 446 conflict = __request_resource(parent, res); 447 if (!conflict) 448 break; 449 if (conflict != parent) { 450 parent = conflict; 451 if (!(conflict->flags & IORESOURCE_BUSY)) 452 continue; 453 } 454 455 /* Uhhuh, that didn't work out.. */ 456 kfree(res); 457 res = NULL; 458 break; 459 }

メモリアドレスの
#define PWM_MR     __phys_to_pfn(PWMC_BASE + PWM_MR_OFF)

コンパイルできます.内核の水が深いので,みんなでよく討論した.