【linux驅動分析】之dm9000驅動分析(二):定義在板文件中的資源和設備以及幾個宏

【linux驅動分析】之dm9000驅動分析(一):dm9000原理及硬件分析 

【linux驅動分析】之dm9000驅動分析(二):定義在板文件中的資源和設備以及幾個宏 

【linux驅動分析】之dm9000驅動分析(三):sk_buff結構分析 

【linux驅動分析】之dm9000驅動分析(四):net_device結構體 

【linux驅動分析】之dm9000驅動分析(五):另外幾個重要的結構體 

【linux驅動分析】之dm9000驅動分析(六):dm9000_init和dm9000_probe的實現 

【linux驅動分析】之dm9000驅動分析(七):dm9000的卸載掛起和恢復以及打開和停止


硬件平臺:友善之臂Tiny6410核心板 + DM9000EP
軟件平臺:linux-2.6.38
交叉編譯器:Friendly ARM提供的arm-linux-gcc 4.5.1
一、源代碼(mach-mini6410.c)
 1 /* Ethernet */
 2 #ifdef CONFIG_DM9000
 3 #define S3C64XX_PA_DM9000    (0x18000000)
 4 #define S3C64XX_SZ_DM9000    SZ_1M
 5 #define S3C64XX_VA_DM9000    S3C_ADDR(0x03b00300)
 6 
 7 static struct resource dm9000_resources[] = {
 8     [0] = {
 9         .start        = S3C64XX_PA_DM9000,
10         .end        = S3C64XX_PA_DM9000 + 3,
11         .flags        = IORESOURCE_MEM,
12     },
13     [1] = {
14         .start        = S3C64XX_PA_DM9000 + 4,
15         .end        = S3C64XX_PA_DM9000 + S3C64XX_SZ_DM9000 - 1,
16         .flags        = IORESOURCE_MEM,
17     },
18     [2] = {
19         .start        = IRQ_EINT(7),
20         .end        = IRQ_EINT(7),
21         .flags        = IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
22     },
23 };
24 
25 static struct dm9000_plat_data dm9000_setup = {
26     .flags            = DM9000_PLATF_16BITONLY | DM9000_PLATF_EXT_PHY,
27     .dev_addr        = { 0x08, 0x90, 0x00, 0xa0, 0x90, 0x90 },
28 };
29 
30 static struct platform_device s3c_device_dm9000 = {
31     .name            = "dm9000",
32     .id                = 0,
33     .num_resources    = ARRAY_SIZE(dm9000_resources),
34     .resource        = dm9000_resources,
35     .dev            = {
36         .platform_data = &dm9000_setup,
37     }
38 };
39 
40 static int __init dm9000_set_mac(char *str) {
41     unsigned char addr[6];
42     unsigned int val;
43     int idx = 0;
44     char *p = str, *end;
45 
46     while (*p && idx < 6) {
47         val = simple_strtoul(p, &end, 16);
48         if (end <= p) {
49             /* convert failed */
50             break;
51         } else {
52             addr[idx++] = val;
53             p = end;
54             if (*p == ':'|| *p == '-') {
55                 p++;
56             } else {
57                 break;
58             }
59         }
60     }
61 
62     if (idx == 6) {
63         printk("Setup ethernet address to %pM\n", addr);
64         memcpy(dm9000_setup.param_addr, addr, 6);
65     }
66 
67     return 1;
68 }
69 
70 __setup("ethmac=", dm9000_set_mac);
71 #endif
72 
73 static struct map_desc mini6410_iodesc[] = {
74     {
75         /* LCD support */
76         .virtual    = (unsigned long)S3C_VA_LCD,
77         .pfn        = __phys_to_pfn(S3C_PA_FB),
78         .length     = SZ_16K,
79         .type       = MT_DEVICE,
80     },
81 #ifdef CONFIG_DM9000           /*這裏的定義不知道是做什麼用的*/
82     {
83         .virtual    = (u32)S3C64XX_VA_DM9000,
84         .pfn        = __phys_to_pfn(S3C64XX_PA_DM9000),
85         .length        = S3C64XX_SZ_DM9000,
86         .type        = MT_DEVICE,
87     },
88 #endif
89 };
DM9000的設備會在
platform_add_devices(mini6410_devices, ARRAY_SIZE(mini6410_devices));
裏統一註冊。

二、下面分析一下上面代碼中紅色的宏或者函數
1、ARRAY_SIZE
  #define  ARRAY_SIZE(arr)   (sizeof(arr) / sizeof( (arr)[0] )  +  __must_be_array(arr) )
它是定義在include/linux/kernel.h中的一個宏,用來計算數組中元素的個數。
__must_be_array是編譯器相關的,用來防止傳入的參數不是數組,比如說傳入了指針,這樣的話可能回編譯不通過(猜測)。
2、simple_strtoul
/**
 * simple_strtoul - convert a string to an unsigned long
 * @cp: The start of the string
 * @endp: A pointer to the end of the parsed string will be placed here
 * @base: The number base to use
 */
unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
simple_strtoul是定義在lib/vsprintf.c中的函數,它的作用是把一個字符串轉換爲unsigned long型的整數,並返回。
其中的endp參數存放解析後的字符串地址,base參數,是要轉換的進制數。
vsprintf.c裏還定義了其他好多字符串處理的函數,具體用到時去查。

3、__setup
它是定義在include/linux/init.h中的一個宏:
#define __setup(str, fn)                    \
    __setup_param(str, fn, fn, 0)

其中:str是關鍵字,fn是關聯處理函數。__setup只是告訴內核在啓動時輸入串中含有str時,內核要去執行fn。Str必須以“=”符結束以使parse_args更方便解析。緊隨“=”後的任何文本都會作爲輸入傳給fn。

例如本例中的:__setup("ethmac=", dm9000_set_mac);
關於__setup的更多分析見《__setup宏的作用》

發佈了52 篇原創文章 · 獲贊 16 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章