我們先檢視核心的啟動資訊,以搞清楚從哪個檔案著手來分析:
s3c24xx nand driver
, (c) 2004 simtec electronics
s3c2440-nand s3c2440-nand: tacls=3, 30ns twrph0=7 70ns, twrph1=3 30ns
nand device: manufacturer id: 0xec, chip id: 0xda (samsung nand 256mib 3,3v 8-bit)
scanning device for bad blocks
bad eraseblock 408 at 0x03300000
bad eraseblock 441 at 0x03720000
bad eraseblock 804 at 0x06480000
bad eraseblock 1155 at 0x09060000
bad eraseblock 1236 at 0x09a80000
creating 4 mtd partitions on "nand 256mib 3,3v 8-bit":
0x00000000-0x00040000 : "bootloader"
0x00040000-0x00060000 : "params"
0x00060000-0x00260000 : "kernel"
0x00260000-0x10000000 : "root"
我們來搜尋:
s3c24xx nand driver
結果我們在drivers\mtd\nand\s3c2410.c檔案裡發現了列印這句話的函式:
static struct platform_driver s3c2440_nand_driver = ,
};
static int __init s3c2410_nand_init(void)
我們看到了,nandflash採用的是平台匯流排裝置機制,當發現名字是
s3c2440-nand的裝置的時候,就會呼叫probe函式,那麼我們就從probe函式入手了:
s3c24xx_nand_probe
s3c2410_nand_inithw(info, pdev);
//初始化硬體
s3c2410_nand_init_chip(info, nmtd, sets);
//初始化晶元,這裡設定了chip的一些資訊
nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1);
//掃瞄晶元
nand_scan_ident(struct mtd_info *mtd, int maxchips)
nand_set_defaults(chip, busw);
//設定預設函式
nand_get_flash_type(mtd, chip, busw, &nand_maf_id);
//獲取nandflash型別
chip->select_chip(mtd, 0);
//選中晶元
chip->cmdfunc(mtd, nand_cmd_readid, 0x00, -1);
//發出讀id的命令,nand_cmd_readid為90h
*maf_id = chip->read_byte(mtd);
//讀廠家id
dev_id = chip->read_byte(mtd);
//讀裝置id
for (i = 0; nand_flash_ids[i].name != null; i++)
//根據裝置id在nand_flash_ids[i]陣列中找到其型別
}
nand_scan_tail(mtd);
//這裡設定了讀寫和擦除函式
mtd->erase = nand_erase;
mtd->read = nand_read;
mtd->write = nand_write;
s3c2410_nand_add_partition(info, nmtd, sets);
//新增分割槽
add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
add_mtd_device(&mtd->mtd);
list_for_each(this, &mtd_notifiers)
//詳見注釋1
注釋1:
list_for_each(this, &mtd_notifiers)
首先我們要搞清楚這個巨集:list_entry(this, struct mtd_notifier, list);它會返回乙個指向
mtd_notifier結構體的指標
這樣我們就明白了,我們需要知道在**定義了mtd_notifier這個東西,這樣才能知道它的成員add函式。我們發現:
void register_mtd_user (struct mtd_notifier *new)
那麼是誰呼叫了 register_mtd_use 函式呢?我們發現:
drivers\mtd\mtd_blkdevs.c和drivers\mtd\mtdchar.c檔案裡面都呼叫了這個函式,這兩個檔案乙個對應字元裝置乙個對應塊裝置,這也說明了nandflash既可以作為字元裝置,也可以作為塊裝置。我們先進入字元裝置看看吧:
很快我們發現了add函式的定義:
static void mtd_notify_add(struct mtd_info* mtd)
我們有必要分析一下這個檔案:
register_chrdev(mtd_char_major, "mtd", &mtd_fops);//註冊字元裝置
class_create(this_module, "mtd");//建立類,但是並沒有在類下建立裝置節點哦,這個節點要在適當的時候才來建立
mtd_notify_add(struct mtd_info* mtd);
我們再來看一下塊裝置驅動的吧:
很快我們就發下了add函式的定義:
static void blktrans_notify_add(struct mtd_info *mtd)
}
不過我們好像還得繼續向上搜尋,我們要看一看是誰設定了blktrans_majors:
int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
那麼我們還要看看register_mtd_blktrans這個函式在**呼叫:
我們在drivers\mtd\mtdblock.c檔案裡面發現了呼叫:
很快我們找到了add函式的定義:
mtdblock_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
add_mtd_blktrans_dev(dev);
alloc_disk(1 << tr->part_bits);
//申請磁碟,一下就可以看出和我們上節課編寫的驅動程式掛鉤了哦!
gd->queue = tr->blkcore_priv->rq;
//設定佇列
add_disk;
//註冊磁碟
針對上面的分析,我們在這裡整理一下,首先來說一說將nandflash當作塊裝置來用的時候,其工作流程:
我們其實是分成了幾個層次的,乙個是塊裝置,我們在之前已經知道了,應用程式對塊裝置的讀寫請求被放放入佇列裡面,也就是說塊裝置對請求作了優化。而我們從s3c2410_nand_add_partition函式分析出來,
mtdblock_add_mtd裡面註冊了這個佇列,那麼請求就可以放在這個佇列裡面,並且這個函式裡面還分配的磁碟並且註冊了磁碟。下面還差一步,那就是對硬體的操作,它在**呢?它就在
nand_scan旗下的函式裡面實現,裡面定義了一些讀寫函式以及擦除函式,可以對硬體進行操作。其實這個框架和我們之前用記憶體模擬磁碟的框架式一致的,不過這裡比較複雜,而且用了分層的概念。
不過這裡面有幾個結構體我們還是要說一下的:
struct nand_chip:用於描述晶元引數
struct mtd_info:定義了大量的mtd裝置資訊以及操作函式
關於字元裝置驅動程式就比較簡單了:在
nand_scan旗下的函式裡面完成了註冊,並設定了操作函式,那樣就可以對nandflash進行操作了。
其實分析道這裡我還不是很明白!希望通過分析接下來的具體程式,我可以更加明白一點!
裝置驅動 塊裝置驅動程式
塊裝置驅動程式提供對面向塊的裝置的訪問,這種裝置以隨機訪問的方式傳輸資料,並且資料總是具有固定大小的塊。典型的塊裝置是磁碟驅動器,也有其它型別的塊裝置。塊裝置和字元裝置有很大區別。比如塊裝置上可以掛載檔案系統,字元裝置不可以。這是隨機訪問帶來的優勢,因為檔案系統需要能按塊儲存資料,同時更需要能隨機讀...
塊裝置驅動程式
裝置描述 定義於linux genhd.h struct gendisk 裝置註冊 void add disk struct gendisk gd 裝置操作 字元裝置通過file operations結構來定義它所支援的操作。塊裝置通過struct block device operations結構...
塊裝置驅動程式
塊裝置驅動程式 1 塊裝置和字元裝置的區別 1,讀取資料的單元不同,塊裝置讀寫資料的基本單元式塊,字元裝置的基本單元是位元組。2,塊裝置可以隨機訪問,字元裝置只能順序訪問。2 linux核心中塊裝置的描述 struct gendisk 裝置操作 struct block device operati...