300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > nand ubi -4 kernel和mtd

nand ubi -4 kernel和mtd

时间:2020-05-16 21:24:51

相关推荐

nand ubi -4 kernel和mtd

tiny6410 linux2.6.38

1.nand驱动

nand是作为平台设备,在板子文件mach-mini6410.c调用,系统启动时自动加载进内核

static struct platform_device *mini6410_devices[] __initdata = {...&s3c_device_nand,...}static void __init mini6410_machine_init(void){...#ifdef CONFIG_MTD_NAND_S3Cs3c_device_nand.name = "s3c6410-nand";//改s3c2410-nand叫s3c6410-nand#endif...platform_add_devices(mini6410_devices, ARRAY_SIZE(mini6410_devices));...}static struct resource s3c_nand_resource[] = {[0] = {.start = S3C_PA_NAND,.end = S3C_PA_NAND + SZ_1M,.flags = IORESOURCE_MEM,}};struct platform_device s3c_device_nand = {.name = "s3c2410-nand",.id = -1,.num_resources = ARRAY_SIZE(s3c_nand_resource),.resource = s3c_nand_resource,};

搜索内核中的s3c6410-nand字符串,在driver/mtd/nand/s3c_nand.c中发现有一处匹配。可以断定这里就是nand的平台驱动

从make menuconfig中也可以得知,如下

Device Drivers ---> <*> Memory Technology Device (MTD) support --->[*] MTD partitioning support

<*> Direct char device access to MTD devices

<*> Caching block device access to MTD devices

<*> NAND Device Support ---> <*> NAND Flash support for S3C SoC

最后一项对应的就是s3c_nand.c,为6410板子配置的nandflash的驱动。下面是平台驱动

s3c_nand.c

static struct platform_driver s3c6410_nand_driver = {.probe= s3c6410_nand_probe,.remove= s3c_nand_remove,.suspend= s3c_nand_suspend,.resume= s3c_nand_resume,.driver= {.name= "s3c6410-nand",.owner= THIS_MODULE,},};

从probe看起,搜索“见下面“

此函数主要对nand_chip结构体chip进行填充。nand_chip描述nand芯片。不同型号的nand,其主要的不同就是nand_chip。

s3c_nand.c

static int s3c6410_nand_probe(struct platform_device *dev){return s3c_nand_probe(dev, TYPE_S3C6410);}/* s3c_nand_probe** called by device layer when it finds a device matching* one our driver can handled. This code checks to see if* it can allocate all necessary resources then calls the* nand layer to look for devices*/static int s3c_nand_probe(struct platform_device *pdev, enum s3c_cpu_type cpu_type){struct s3c2410_platform_nand *plat = pdev->dev.platform_data;struct s3c2410_nand_set *sets;struct nand_chip *nand;struct resource *res;struct mtd_partition *partitions;int nr_partitions;int err = 0;int ret = 0;int nr_sets;int i, j, size;#if defined(CONFIG_MTD_NAND_S3C_HWECC)//硬件eccstruct nand_flash_dev *type = NULL;u_char tmp;#endif/* get the clock source and enable it */s3c_nand.clk = clk_get(&pdev->dev, "nand");if (IS_ERR(s3c_nand.clk)) {dev_err(&pdev->dev, "failed to get clock");err = -ENOENT;goto exit_error;}clk_enable(s3c_nand.clk);/* allocate and map the resource *//* currently we assume we have the one resource */res = pdev->resource;size = res->end - res->start + 1;s3c_nand.area = request_mem_region(res->start, size, pdev->name);if (s3c_nand.area == NULL) {dev_err(&pdev->dev, "cannot reserve register region\n");err = -ENOENT;goto exit_error;}s3c_nand.cpu_type = cpu_type;s3c_nand.device= &pdev->dev;s3c_nand.regs = ioremap(res->start, size);s3c_nand.platform = plat;if (s3c_nand.regs == NULL) {dev_err(&pdev->dev, "cannot reserve register region\n");err = -EIO;goto exit_error;}sets = (plat != NULL) ? plat->sets : NULL;nr_sets = (plat != NULL) ? plat->nr_sets : 1;/* Using partition info from platform data for SLC nand */partitions = sets->partitions;//使用mach-mini6410.c中定义的分区表给nand分区(SLC)。如果是MLC,后面会指定其他分区表。nr_partitions = sets->nr_partitions;s3c_nand.mtd_count = nr_sets;/* allocate memory for MTD device structure and private data */s3c_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);if (!s3c_mtd) {printk("Unable to allocate NAND MTD dev structure.\n");return -ENOMEM;}/* Get pointer to private data */nand = (struct nand_chip *) (&s3c_mtd[1]);/* Initialize structures */memset((char *) s3c_mtd, 0, sizeof(struct mtd_info));memset((char *) nand, 0, sizeof(struct nand_chip));/* Link the private data with the MTD structure */s3c_mtd->priv = nand;for (i = 0; i < sets->nr_chips; i++) {nand->IO_ADDR_R= (char *)(s3c_nand.regs + S3C_NFDATA);nand->IO_ADDR_W= (char *)(s3c_nand.regs + S3C_NFDATA);nand->cmd_ctrl= s3c_nand_hwcontrol;nand->dev_ready= s3c_nand_device_ready;nand->scan_bbt= s3c_nand_scan_bbt;nand->options= 0;nand->badblockbits= 8;#ifdef CONFIG_MACH_MINI6410s3c_nand_ext_finit(nand, s3c_nand.regs);#endif#if defined(CONFIG_MTD_NAND_S3C_CACHEDPROG)nand->options|= NAND_CACHEPRG;#endif#if defined(CONFIG_MTD_NAND_S3C_HWECC)nand->ecc.mode= NAND_ECC_HW;nand->ecc.hwctl= s3c_nand_enable_hwecc;nand->ecc.calculate= s3c_nand_calculate_ecc;nand->ecc.correct= s3c_nand_correct_data;s3c_nand_hwcontrol(0, NAND_CMD_READID, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);s3c_nand_hwcontrol(0, 0x00, NAND_CTRL_CHANGE | NAND_NCE | NAND_ALE);s3c_nand_hwcontrol(0, 0x00, NAND_NCE | NAND_ALE);s3c_nand_hwcontrol(0, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);s3c_nand_device_ready(0);tmp = readb(nand->IO_ADDR_R); /* Maf. ID */tmp = readb(nand->IO_ADDR_R); /* Device ID */for (j = 0; nand_flash_ids[j].name != NULL; j++) {if (tmp == nand_flash_ids[j].id) {type = &nand_flash_ids[j];break;}}if (!type) {printk("Unknown NAND Device.\n");goto exit_error;}nand->cellinfo = readb(nand->IO_ADDR_R);/* the 3rd byte */tmp = readb(nand->IO_ADDR_R);/* the 4th byte */if (!type->pagesize) {if (((nand->cellinfo >> 2) & 0x3) == 0) {//SLCnand_type = S3C_NAND_TYPE_SLC;nand->ecc.size = 512;每次进行ecc的数据量(以子页位单位),bytes per ecc step.每页进行4次,共计2KBnand->ecc.bytes= 4;每次ecc校验字节,ecc bytes per step。每页进行4次。共计16字节if ((1024 << (tmp & 0x3)) > 512) {//对于1GB SLC而言nand->ecc.read_page = s3c_nand_read_page_1bit;//SLC使用1位ecc nand->ecc.write_page = s3c_nand_write_page_1bit;nand->ecc.read_oob = s3c_nand_read_oob_1bit;nand->ecc.write_oob = s3c_nand_write_oob_1bit;nand->ecc.layout = &s3c_nand_oob_64;//1GB SLC的oob大小是64,见下面} else {nand->ecc.layout = &s3c_nand_oob_16;}} else {//MLCnand_type = S3C_NAND_TYPE_MLC;nand->options |= NAND_NO_SUBPAGE_WRITE;/* NOP = 1 if MLC */if (type->id == 0xD5) {#if0type->chipsize = 2076;nand->chip_shift = 32;nand->pagemask = 0x7ffff;#endifnand->badblockbits = 4;}if ((2048 << (tmp & 3)) < 4096) {nand->ecc.read_page = s3c_nand_read_page_4bit;//MLC使用4位eccnand->ecc.write_page = s3c_nand_write_page_4bit;nand->ecc.size = 512;nand->ecc.bytes = 8;/* really 7 bytes */nand->ecc.layout = &s3c_nand_oob_mlc_64;} else {#ifdef CONFIG_MACH_MINI6410partitions = mini6410_nand_part_mlc;//使用s3c_nand.c中定义的分区表给MLC分区nr_partitions = ARRAY_SIZE(mini6410_nand_part_mlc);s3c_nand_mlc_probe(nand, s3c_nand.regs);#endif}}} else {nand_type = S3C_NAND_TYPE_SLC;nand->ecc.size = 512;nand->cellinfo = 0;nand->ecc.bytes = 4;nand->ecc.layout = &s3c_nand_oob_16;}printk("S3C NAND Driver is using hardware ECC.\n");#else//软件eccnand->ecc.mode = NAND_ECC_SOFT;printk("S3C NAND Driver is using software ECC.\n");#endifif (nand_scan(s3c_mtd, 1)) {//扫描nand,并初始化s3c_mtd结构体里的一些函数指针ret = -ENXIO;goto exit_error;}/* Register the partitions */add_mtd_partitions(s3c_mtd, partitions, nr_partitions);//分区,见下面}pr_debug("initialized ok\n");return 0;exit_error:kfree(s3c_mtd);return ret;}

s3c_nand.c

/* Nand flash oob definition for SLC 2k page size by jsgood */ static struct nand_ecclayout s3c_nand_oob_64 = { .eccbytes = 16, .eccpos = {40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55}, .oobfree = { {.offset = 2, .length = 38}} }; //对于K9K8G0800B 1GB SLC,页大小是2KB, oob是64B,地址认为是0-63 ecc字节数16(所占地址从40-55,共计16字节) oob中空闲字节数38(所占地址从2-39) oob中剩余余的0-1和56-63另有用途

nand_scan会调用nand_scan_tail函数扫描nand,并使用nand_base.c中预定义的一些读写nand的函数来初始化mtd_info结构体的函数指针。

这个mtd_info会在稍后add_mtd_partitions时给各个分区的mtd_info赋值。

nand_base.c

/*** nand_scan_tail - [NAND Interface] Scan for the NAND device* @mtd: MTD device structure** This is the second phase of the normal nand_scan() function. It* fills out all the uninitialized function pointers with the defaults* and scans for a bad block table if appropriate.*/int nand_scan_tail(struct mtd_info *mtd){int i;struct nand_chip *chip = mtd->priv;if (!(chip->options & NAND_OWN_BUFFERS))chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL);if (!chip->buffers)return -ENOMEM;/* Set the internal oob buffer location, just after the page data */chip->oob_poi = chip->buffers->databuf + mtd->writesize;/** If no default placement scheme is given, select an appropriate one*/if (!chip->ecc.layout) {switch (mtd->oobsize) {case 8:chip->ecc.layout = &nand_oob_8;break;case 16:chip->ecc.layout = &nand_oob_16;break;case 64:chip->ecc.layout = &nand_oob_64;break;case 128:chip->ecc.layout = &nand_oob_128;break;default:printk(KERN_WARNING "No oob scheme defined for ""oobsize %d\n", mtd->oobsize);BUG();}}if (!chip->write_page)chip->write_page = nand_write_page;/** check ECC mode, default to software if 3byte/512byte hardware ECC is* selected and we have 256 byte pagesize fallback to software ECC*/switch (chip->ecc.mode) {case NAND_ECC_HW_OOB_FIRST:/* Similar to NAND_ECC_HW, but a separate read_page handle */if (!chip->ecc.calculate || !chip->ecc.correct ||!chip->ecc.hwctl) {printk(KERN_WARNING "No ECC functions supplied; ""Hardware ECC not possible\n");BUG();}if (!chip->ecc.read_page)chip->ecc.read_page = nand_read_page_hwecc_oob_first;case NAND_ECC_HW:/* Use standard hwecc read page function ? */if (!chip->ecc.read_page)chip->ecc.read_page = nand_read_page_hwecc;if (!chip->ecc.write_page)chip->ecc.write_page = nand_write_page_hwecc;if (!chip->ecc.read_page_raw)chip->ecc.read_page_raw = nand_read_page_raw;if (!chip->ecc.write_page_raw)chip->ecc.write_page_raw = nand_write_page_raw;if (!chip->ecc.read_oob)chip->ecc.read_oob = nand_read_oob_std;if (!chip->ecc.write_oob)chip->ecc.write_oob = nand_write_oob_std;case NAND_ECC_HW_SYNDROME:if ((!chip->ecc.calculate || !chip->ecc.correct ||!chip->ecc.hwctl) &&(!chip->ecc.read_page ||chip->ecc.read_page == nand_read_page_hwecc ||!chip->ecc.write_page ||chip->ecc.write_page == nand_write_page_hwecc)) {printk(KERN_WARNING "No ECC functions supplied; ""Hardware ECC not possible\n");BUG();}/* Use standard syndrome read/write page function ? */if (!chip->ecc.read_page)chip->ecc.read_page = nand_read_page_syndrome;if (!chip->ecc.write_page)chip->ecc.write_page = nand_write_page_syndrome;if (!chip->ecc.read_page_raw)chip->ecc.read_page_raw = nand_read_page_raw_syndrome;if (!chip->ecc.write_page_raw)chip->ecc.write_page_raw = nand_write_page_raw_syndrome;if (!chip->ecc.read_oob)chip->ecc.read_oob = nand_read_oob_syndrome;if (!chip->ecc.write_oob)chip->ecc.write_oob = nand_write_oob_syndrome;if (mtd->writesize >= chip->ecc.size)break;printk(KERN_WARNING "%d byte HW ECC not possible on ""%d byte page size, fallback to SW ECC\n",chip->ecc.size, mtd->writesize);chip->ecc.mode = NAND_ECC_SOFT;case NAND_ECC_SOFT:chip->ecc.calculate = nand_calculate_ecc;chip->ecc.correct = nand_correct_data;chip->ecc.read_page = nand_read_page_swecc;chip->ecc.read_subpage = nand_read_subpage;chip->ecc.write_page = nand_write_page_swecc;chip->ecc.read_page_raw = nand_read_page_raw;chip->ecc.write_page_raw = nand_write_page_raw;chip->ecc.read_oob = nand_read_oob_std;chip->ecc.write_oob = nand_write_oob_std;if (!chip->ecc.size)chip->ecc.size = 256;chip->ecc.bytes = 3;break;case NAND_ECC_NONE:printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. ""This is not recommended !!\n");chip->ecc.read_page = nand_read_page_raw;chip->ecc.write_page = nand_write_page_raw;chip->ecc.read_oob = nand_read_oob_std;chip->ecc.read_page_raw = nand_read_page_raw;chip->ecc.write_page_raw = nand_write_page_raw;chip->ecc.write_oob = nand_write_oob_std;chip->ecc.size = mtd->writesize;chip->ecc.bytes = 0;break;default:printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",chip->ecc.mode);BUG();}/** The number of bytes available for a client to place data into* the out of band area*/chip->ecc.layout->oobavail = 0;for (i = 0; chip->ecc.layout->oobfree[i].length&& i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++)chip->ecc.layout->oobavail +=chip->ecc.layout->oobfree[i].length;mtd->oobavail = chip->ecc.layout->oobavail;/** Set the number of read / write steps for one page depending on ECC* mode*/chip->ecc.steps = mtd->writesize / chip->ecc.size;if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {printk(KERN_WARNING "Invalid ecc parameters\n");BUG();}chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;/** Allow subpage writes up to ecc.steps. Not possible for MLC* FLASH.*/if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&!(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {switch (chip->ecc.steps) {case 2:mtd->subpage_sft = 1;break;case 4:case 8:case 16:mtd->subpage_sft = 2;break;}}chip->subpagesize = mtd->writesize >> mtd->subpage_sft;/* Initialize state */chip->state = FL_READY;/* De-select the device */chip->select_chip(mtd, -1);/* Invalidate the pagebuffer reference */chip->pagebuf = -1;/* Fill in remaining MTD driver data */mtd->type = MTD_NANDFLASH;mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM :MTD_CAP_NANDFLASH;mtd->erase = nand_erase;mtd->point = NULL;mtd->unpoint = NULL;mtd->read = nand_read;mtd->write = nand_write;mtd->panic_write = panic_nand_write;mtd->read_oob = nand_read_oob;mtd->write_oob = nand_write_oob;mtd->sync = nand_sync;mtd->lock = NULL;mtd->unlock = NULL;mtd->suspend = nand_suspend;mtd->resume = nand_resume;mtd->block_isbad = nand_block_isbad;mtd->block_markbad = nand_block_markbad;mtd->writebufsize = mtd->writesize;/* propagate ecc.layout to mtd_info */mtd->ecclayout = chip->ecc.layout;/* Check, if we should skip the bad block table scan */if (chip->options & NAND_SKIP_BBTSCAN)return 0;/* Build bad block table */return chip->scan_bbt(mtd);}

add_mtd_partitions函数会循环调用nr_partitions次allocate_partition函数来给flash分为nr_partitions个区

每个分区使用一个mtd_part描述,而mtd_part中都有一个mtd_info结构体用于具体描述这个分区。此mtd_info中的结构体的函数指针很多都执行master的函数。而master就是上面执行nand_scan_tail时,被初始化的一个mtd_info结构体。

mtdpart.c

static struct mtd_part *allocate_partition(struct mtd_info *master,const struct mtd_partition *part, int partno,uint64_t cur_offset){struct mtd_part *slave;char *name;/* allocate the partition structure */slave = kzalloc(sizeof(*slave), GFP_KERNEL);name = kstrdup(part->name, GFP_KERNEL);if (!name || !slave) {printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n",master->name);kfree(name);kfree(slave);return ERR_PTR(-ENOMEM);}/* set up the MTD object for this partition */slave->mtd.type = master->type;slave->mtd.flags = master->flags & ~part->mask_flags;slave->mtd.size = part->size;slave->mtd.writesize = master->writesize;slave->mtd.writebufsize = master->writebufsize;slave->mtd.oobsize = master->oobsize;slave->mtd.oobavail = master->oobavail;slave->mtd.subpage_sft = master->subpage_sft;slave->mtd.name = name;slave->mtd.owner = master->owner;slave->mtd.backing_dev_info = master->backing_dev_info;/* NOTE: we don't arrange MTDs as a tree; it'd be error-prone* to have the same data be in two different partitions.*/slave->mtd.dev.parent = master->dev.parent;slave->mtd.read = part_read;slave->mtd.write = part_write;if (master->panic_write)slave->mtd.panic_write = part_panic_write;if (master->point && master->unpoint) {slave->mtd.point = part_point;slave->mtd.unpoint = part_unpoint;}if (master->get_unmapped_area)slave->mtd.get_unmapped_area = part_get_unmapped_area;if (master->read_oob)slave->mtd.read_oob = part_read_oob;if (master->write_oob)slave->mtd.write_oob = part_write_oob;if (master->read_user_prot_reg)slave->mtd.read_user_prot_reg = part_read_user_prot_reg;if (master->read_fact_prot_reg)slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;if (master->write_user_prot_reg)slave->mtd.write_user_prot_reg = part_write_user_prot_reg;if (master->lock_user_prot_reg)slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;if (master->get_user_prot_info)slave->mtd.get_user_prot_info = part_get_user_prot_info;if (master->get_fact_prot_info)slave->mtd.get_fact_prot_info = part_get_fact_prot_info;if (master->sync)slave->mtd.sync = part_sync;if (!partno && !master->dev.class && master->suspend && master->resume) {slave->mtd.suspend = part_suspend;slave->mtd.resume = part_resume;}if (master->writev)slave->mtd.writev = part_writev;if (master->lock)slave->mtd.lock = part_lock;if (master->unlock)slave->mtd.unlock = part_unlock;if (master->is_locked)slave->mtd.is_locked = part_is_locked;if (master->block_isbad)slave->mtd.block_isbad = part_block_isbad;if (master->block_markbad)slave->mtd.block_markbad = part_block_markbad;slave->mtd.erase = part_erase;slave->master = master;slave->offset = part->offset;if (slave->offset == MTDPART_OFS_APPEND)slave->offset = cur_offset;if (slave->offset == MTDPART_OFS_NXTBLK) {slave->offset = cur_offset;if (mtd_mod_by_eb(cur_offset, master) != 0) {/* Round up to next erasesize */slave->offset = (mtd_div_by_eb(cur_offset, master) + 1) * master->erasesize;printk(KERN_NOTICE "Moving partition %d: ""0x%012llx -> 0x%012llx\n", partno,(unsigned long long)cur_offset, (unsigned long long)slave->offset);}}if (slave->mtd.size == MTDPART_SIZ_FULL)slave->mtd.size = master->size - slave->offset;printk(KERN_NOTICE "0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset,(unsigned long long)(slave->offset + slave->mtd.size), slave->mtd.name);/* let's do some sanity checks */if (slave->offset >= master->size) {/* let's register it anyway to preserve ordering */slave->offset = 0;slave->mtd.size = 0;printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n",part->name);goto out_register;}if (slave->offset + slave->mtd.size > master->size) {slave->mtd.size = master->size - slave->offset;printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#llx\n",part->name, master->name, (unsigned long long)slave->mtd.size);}if (master->numeraseregions > 1) {/* Deal with variable erase size stuff */int i, max = master->numeraseregions;u64 end = slave->offset + slave->mtd.size;struct mtd_erase_region_info *regions = master->eraseregions;/* Find the first erase regions which is part of this* partition. */for (i = 0; i < max && regions[i].offset <= slave->offset; i++);/* The loop searched for the region _behind_ the first one */if (i > 0)i--;/* Pick biggest erasesize */for (; i < max && regions[i].offset < end; i++) {if (slave->mtd.erasesize < regions[i].erasesize) {slave->mtd.erasesize = regions[i].erasesize;}}BUG_ON(slave->mtd.erasesize == 0);} else {/* Single erase size */slave->mtd.erasesize = master->erasesize;}if ((slave->mtd.flags & MTD_WRITEABLE) &&mtd_mod_by_eb(slave->offset, &slave->mtd)) {/* Doesn't start on a boundary of major erase size *//* FIXME: Let it be writable if it is on a boundary of* _minor_ erase size though */slave->mtd.flags &= ~MTD_WRITEABLE;printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n",part->name);}if ((slave->mtd.flags & MTD_WRITEABLE) &&mtd_mod_by_eb(slave->mtd.size, &slave->mtd)) {slave->mtd.flags &= ~MTD_WRITEABLE;printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n",part->name);}slave->mtd.ecclayout = master->ecclayout;if (master->block_isbad) {uint64_t offs = 0;while (offs < slave->mtd.size) {if (master->block_isbad(master,offs + slave->offset))slave->mtd.ecc_stats.badblocks++;offs += slave->mtd.erasesize;}}out_register:return slave;}

有个疑问

nand_chip的ecc结构体有很多读写函数,ecc结构体的函数指针在nand_scan_tail中被赋值,比如

/* Use standard hwecc read page function ? */

if (!chip->ecc.read_page)

chip->ecc.read_page = nand_read_page_hwecc;

if (!chip->ecc.write_page)

chip->ecc.write_page = nand_write_page_hwecc;

if (!chip->ecc.read_page_raw)

chip->ecc.read_page_raw = nand_read_page_raw;

if (!chip->ecc.write_page_raw)

chip->ecc.write_page_raw = nand_write_page_raw;

if (!chip->ecc.read_oob)

chip->ecc.read_oob = nand_read_oob_std;

if (!chip->ecc.write_oob)

chip->ecc.write_oob = nand_write_oob_std;

而每个分区mtd_part结构体的mtd_info结构体也有很多读写函数,函数指针在allocate_partition中被赋值,比如

slave->mtd.read = part_read;

slave->mtd.write = part_write;

if (master->panic_write)

slave->mtd.panic_write = part_panic_write;

if (master->point && master->unpoint) {

slave->mtd.point = part_point;

slave->mtd.unpoint = part_unpoint;

}

if (master->get_unmapped_area)

slave->mtd.get_unmapped_area = part_get_unmapped_area;

if (master->read_oob)

slave->mtd.read_oob = part_read_oob;

if (master->write_oob)

slave->mtd.write_oob = part_write_oob;

if (master->read_user_prot_reg)

slave->mtd.read_user_prot_reg = part_read_user_prot_reg;

if (master->read_fact_prot_reg)

slave->mtd.read_fact_prot_reg = part_read_fact_prot_reg;

if (master->write_user_prot_reg)

slave->mtd.write_user_prot_reg = part_write_user_prot_reg;

if (master->lock_user_prot_reg)

slave->mtd.lock_user_prot_reg = part_lock_user_prot_reg;

if (master->get_user_prot_info)

slave->mtd.get_user_prot_info = part_get_user_prot_info;

if (master->get_fact_prot_info)

slave->mtd.get_fact_prot_info = part_get_fact_prot_info;

if (master->sync)

slave->mtd.sync = part_sync;

if (!partno && !master->dev.class && master->suspend && master->resume) {

slave->mtd.suspend = part_suspend;

slave->mtd.resume = part_resume;

}

if (master->writev)

slave->mtd.writev = part_writev;

if (master->lock)

slave->mtd.lock = part_lock;

if (master->unlock)

slave->mtd.unlock = part_unlock;

if (master->is_locked)

slave->mtd.is_locked = part_is_locked;

if (master->block_isbad)

slave->mtd.block_isbad = part_block_isbad;

if (master->block_markbad)

slave->mtd.block_markbad = part_block_markbad;

slave->mtd.erase = part_erase;

slave->master = master;

slave->offset = part->offset;

这两个结构体的读写函数有啥不同呢?待续。。。。。

2.内核加载ubi

mtdchar.c

mtdblock.c

加载mtd分区上的文件系统后,执行文件系统根目录的linuxrc(因为setenv bootargs console=ttySAC0 noinitrd root=/dev/mtdblock3 init=/linuxrc)和init

见内核源码init/main.cinit_post()

if (execute_command) {run_init_process(execute_command);//init=/linuxrcprintk(KERN_WARNING "Failed to execute %s. Attempting ""defaults...\n", execute_command);}run_init_process("/sbin/init");run_init_process("/etc/init");run_init_process("/bin/init");run_init_process("/bin/sh");panic("No init found. Try passing init= option to kernel. ""See Linux Documentation/init.txt for guidance.");

/blog/543595

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。