Intel StrataFlash 等 NOR 閃存支援多分區操作,但在 Linux 2.4 時代常導致「Magic bitmask not found」錯誤,根因是驅動僅用單一狀態變數追蹤整顆晶片,與分區實際狀態脫節。Linux 2.6.13 後 MTD 子系統重構解決此問題。本文深入剖析 MTD/Map/Chip 三層架構、CFI 探測流程與多分區虛擬 Chip 機制。
cfi_util.c 中 cfi_read_pri 實作。map_info 指定基址/位寬/大小,呼叫 do_map_probe("cfi_probe", ...)。do_map_probe 依名稱找到 cfi_probe.c,呼叫 cfi_probe()。cfi_probe() 呼叫 mtd_do_chip_probe(),傳入 cfi_probe_chip 函數指標。mtd_do_chip_probe() 兩階段:
genprobe_ident_chips() 探測晶片資訊(大小、位寬、互留數)check_cmd_set() 取得並初始化指令集(含多分區初始化)genprobe_ident_chips() 呼叫 genprobe_new_chip() 枚舉各種位寬/互留組合,調用 cfi_probe_chip()。通常第一次調用成功(編譯時確定連接方式)。cfi_probe_chip() → cfi_chip_setup() 讀取 CFI 資訊(Primary/Extended Query Table)。check_cmd_set() → cfi_cmdset_0001() (Intel/Sharp 指令集):
read_pri_intelext() 讀取 Intel Extended Primary Table(含分區資訊)cfi_intelext_setup() 初始化結構區塊結構:4×32KB + 127×128KB = 16MB,共 16 分區,每分區 1MB,nb_parts=2(兩組相同分區結構)。
第 1 部分: NumIdentPartitions = 1 // 1 個重複分區結構 NumBlockTypes = 2 // 2 種區塊類型 類型 1:NumIdentBlocks=3 (4 個區塊), BlockSize=0x80 (32KB) 類型 2:NumIdentBlocks=6 (7 個區塊), BlockSize=0x200 (128KB) 第 2 部分: NumIdentPartitions = 15 // 15 個重複分區結構 NumBlockTypes = 1 類型 1:NumIdentBlocks=7 (8 個區塊), BlockSize=0x200 (128KB)
cfi_intelext_partition_fixup)為支援多分區並行操作,驅動將每個分區對應一個虛擬 Chip:
cfi->chipshift 調整為 partshift (分區大小對應的位移量)。start 設為分區基址。cfi_varsize_frob() 依 offset 計算 chipnum = ofs >> cfi->chipshift 導向對應虛擬 Chip。Linux 擦寫前不先 Unlock,解法:初始化時對全晶片執行 Unlock 指令。