};
static void __exit cfi_probe_exit(void) {
unregister_mtd_chip_driver(&cfi_chipdrv); };
函数cfi_probe调用mtd_do_chip_probe函数来完成了探测操作,在函数cfi_chip_probe中,它调用qry_present来查询是否是CFI接口,调用函数cfi_chip_setup)初始化cfi_private结构,调用函数cfi_chip_setup则读出CFI查询结构中的数据。然后,函数mtd_do_chip_probe调用函数check_cmd_set根据map_info中的信息来设备不同的命令集:cfi_cmdset_0001()或
cfi_cmdset_0002(),如果符合的类型没有则调用cfi_cmdset_unkown。 函数cfi_probe列出如下:
struct mtd_info *cfi_probe(struct map_info *map) {
return mtd_do_chip_probe(map, &cfi_chip_probe); }
static struct chip_probe cfi_chip_probe = { .name = “CFI”, .probe_chip = cfi_probe_chip };
(2)映射驱动程序
用户可设置flash空间映射信息填充在映射驱动程序中,包括该MTD原始设备的起始物理地址、大小、分区情况等。映射驱动程序都在drivers/mtd/maps子目录下。这里简单说明cfi_flagadm映射驱动程序(在cfi_flagadm.c中)。 flagadm_map是映射信息结构,它含有flash存储空间的配置信息,列出如下: struct map_info flagadm_map = { .name = “FlagaDM flash device”, .size = FLASH_SIZE, .bankwidth = 2,
};
flagadm_parts是flash存储空间的分区,列出如下: struct mtd_partition flagadm_parts[] = { {
.name = “Bootloader”, .offset = FLASH_PARTITION0_ADDR, .size = FLASH_PARTITION0_SIZE }, {
.name = “Kernel image”, .offset = FLASH_PARTITION1_ADDR, .size = FLASH_PARTITION1_SIZE }, {
.name = “Initial ramdisk image”, .offset = FLASH_PARTITION2_ADDR, .size = FLASH_PARTITION2_SIZE }, {
.name = “Persistant storage”, .offset = FLASH_PARTITION3_ADDR, .size = FLASH_PARTITION3_SIZE } };
#define PARTITION_COUNT (sizeof(flagadm_parts)/sizeof(struct mtd_partition?pan>
static struct mtd_info *mymtd;
函数init_flagadm是映射驱动程序的初始化,它得到了端口映射地址,初始化了操作函数,通过探测函数得到MTD设备结构。函数init_flagadm说明如下: int __init init_flagadm(void) {
printk(KERN_NOTICE “FlagaDM flash device: %x at %x\\n”, FLASH_SIZE, FLASH_PHYS_ADDR); flagadm_map.phys = FLASH_PHYS_ADDR;
//端口映射
flagadm_map.virt = ioremap(FLASH_PHYS_ADDR,FLASH_SIZE); if (!flagadm_map.virt) {
printk(“Failed to ioremap\\n”); return -EIO; }
//赋上通用的读写操作函数,如:__raw_writeb等 simple_map_init(&flagadm_map);
//探测CFI类型接口得到MTD设备结构
mymtd = do_map_probe(“cfi_probe”, &flagadm_map); if (mymtd) {
mymtd->owner = THIS_MODULE;
//将分区信息加到MTD设备结构实例mymtd中
add_mtd_partitions(mymtd, flagadm_parts, PARTITION_COUNT); printk(KERN_NOTICE “FlagaDM flash device initialized\\n”); return 0; }
iounmap((void *)flagadm_map.virt);//取消端口映射 return -ENXIO; }
static void __exit cleanup_flagadm(void) {
if (mymtd) {
del_mtd_partitions(mymtd); map_destroy(mymtd); }
if (flagadm_map.virt) {
iounmap((void *)flagadm_map.virt); flagadm_map.virt = 0; } }
SD/MMC卡块设备驱动程序
SD/MMC卡组成的存储系统是许多嵌入设备的主要存储设备,相当于PC机的硬盘,在嵌入设备上的SD/MMC卡控制器通过MMC协议来解析命令控制SD/MMC卡的操作。SD/MMC卡上有一些寄存器来控制卡的状态及读写操作。MMC协议规定的寄存器有:CID寄存器,128位,是卡的鉴别寄存器,存有卡的鉴别信息;RCA寄存器是16位,存有卡的本地系统的相对地址,在初始化时由控制器动态指定。DSR寄存器是16位,是配置卡的驱动程序的寄存器,是可选的。CSD寄存器是卡特定数据信息描述寄存器,是可选的。OCR寄存器是操作控制寄存器。MMC卡的系统定义及相关协议请查询《MMC卡系统定义3.1版本》。
MMC驱动程序以分通用设备层、MMC抽象设备层、MMC协议层和具体设备层四层来构建,上一层抽象出下一层的共有特性,每一层以相应的结构来描述。通用设备层对于块设备来说,主要负责设备内核对象在sysfs文件系统中的管理、请求队列管理、及与文件系统的接口,MMC抽象设备层抽出MMC卡的共有特性,如: MMC卡的请求管理、电源管理等。MMC协议层将MMC操作分解成标准的MMC协议,具体设备层则负责具体物理设备的寄存器控制等。这种分层结构层次分明,管理有效。MMC驱动程序的层次结构如下图。
MMC驱动程序主要处理两部分的内容,一是创建通用硬盘结构向系统注册,以便系统对MMC设备的管理。另一方面,要完成系统分发过来的读写请求的处理。
图 MMC驱动程序的层次结构
MMC抽象设备层相关结构
(1)设备描述结构
图 MMC卡设备相关结构关系图
MMC设备由控制器及插卡组成,对应的设备结构为mmc_host结构和mmc_card结构。MMC卡设备相关结构关系图如上图。下面分别说明设备相关结构: 每个卡的插槽对应一个块的数据结构mmc_blk_data,结构列出如下(在drivers/mmc/mmc_block.c中):
struct mmc_blk_data { spinlock_t lock; struct gendisk *disk; //通用硬盘结构 struct mmc_queue queue; //MMC请求队列结构