/*=========================================================================== FUNCTION FLASH_NAND_OPER_REGION_INIT DESCRIPTION Initilize user partition info,and get the handle of nand flash RETURN VALUE TRUE if Op Succeed FALSE if Op Failure SIDE EFFECTS None ===========================================================================*/ oper_region_struct_t *flash_nand_oper_region_init( oper_region_type oper_region_idx) { uint8 idx = (uint8)oper_region_idx; char *parent_name_ptr = NULL; unsigned int offset = 0; /* 范围保护 */ if (idx >= REGION_MAX) { printk(KERN_ERR "Parm error: idx = %d max_ids = %d\n",idx,REGION_MAX); return NULL; } /*lint -e662*/ parent_name_ptr = (char *)child_region[idx].parent_name; printk(KERN_DEBUG "parent_name_ptr =%s \n",parent_name_ptr); /*lint +e662*/ /*lint -e661*/ offset = child_region[idx].offset; /*lint +e661*/ /* get mtd device */ g_mtd = get_mtd_device_nm(parent_name_ptr); if (NULL == g_mtd) { printk(KERN_ERR "get_mtd_device_nm error\n"); return NULL; } printk(" info :mtd->erasesize = %d ,mtd->writesize = %d \n", g_mtd->erasesize,g_mtd->writesize); /* get the flash address */ operation_region[idx].block_size = g_mtd->erasesize; operation_region[idx].page_size = g_mtd->writesize; operation_region[idx].start_addr = (offset * operation_region[idx].block_size); operation_region[idx].buffer = himalloc(operation_region[idx].page_size); printk(KERN_DEBUG "operation_region[%d] = %u \n", idx, (unsigned int)operation_region[idx].start_addr); if (NULL == operation_region[idx].buffer) { put_mtd_device(g_mtd); return NULL; } /* 初始化读写flash时使用的缓冲区 */ memset((void *)operation_region[idx].buffer, NAND_FILL_CHAR_APP, operation_region[idx].page_size); return &operation_region[idx]; }
/** * 作用:读取分区相对偏移地址的标志值,主要是为NV模块用,查询此分区的偏移地址的标志位的值 * * 参数: * @partition_name ---分区名 * @partition_offset ---分区的相对偏移 * @flag ---把检测的分区的标志值存放在此flag中 * 描述:NV模块把一个分区的一个block的最后一页的OOB中存放特定标记值,读此标记值存放在flag中 */ u32 bsp_nand_read_flag_nv(const char *partition_name, u32 partition_offset, unsigned char *flag) { u32 flash_addr; u32 ret = NANDC_ERROR; static unsigned char *buffer = NULL; struct nand_spec spec; struct ST_PART_TBL * ptable = find_partition_by_name((char *)partition_name); /*参数不对*/ if(!ptable) { goto ERRO; } if(!flag) { NAND_TRACE(("argu error.\n")); goto ERRO; } /*得到此分区的nandflash的规格参数*/ ret = bsp_get_nand_info(&spec); if(ret) { goto ERRO; } /*没有内存时分配内存*/ if(!buffer) { buffer = (unsigned char *)himalloc(spec.pagesize + YAFFS_BYTES_PER_SPARE); if(!buffer) { NAND_TRACE(("get ram buffer failed!\n")); goto ERRO; } } memset(buffer, 0xFF, spec.pagesize + YAFFS_BYTES_PER_SPARE); flash_addr = ptable->offset + partition_offset; /*使能ECC功能的带OOB读数据功能*/ ret = nand_read_oob((flash_addr + spec.blocksize - spec.pagesize), (unsigned int)buffer, (spec.pagesize + YAFFS_BYTES_PER_SPARE),YAFFS_BYTES_PER_SPARE ,NULL); if(ret) { NAND_TRACE(("nand read oob failed!\n")); goto ERRO; } *flag = (*(buffer + spec.pagesize) == NV_WRITE_SUCCESS) ? NV_WRITE_SUCCESS : (~NV_WRITE_SUCCESS); return NANDC_OK; ERRO: return ret; }
/** * 作用:nandc模块提供对外扫描坏块的函数接口 * * 参数: * @start ---flash开始的地址 * @length ---扫描的长度 * @if_erase ---如果检测是好块根据此参数来决定是否擦除此块 * 描述:扫描flash是否是坏块,根据参数来决定是否擦除 */ u32 nand_scan_bad(FSZ start, FSZ length, u32 if_erase) { u32 addr_block_align; u32 length_block_align; u32 blk_id, is_bad, times, ret; struct nand_spec spec; /*因为是在fastboot中实现,内存的释放是没有实现的,使用静态变量表示一次分配以后都不分配了*/ static u32 block_buf = 0 ; memset(&spec, 0, sizeof(struct nand_spec)); /*通过此函数得到nandflash的规格参数,知道blocksize的大小*/ if(NAND_OK != nand_get_spec(&spec)) { NAND_TRACE(("nand_scan_bad: nand_get_spec failed\n")); return NAND_ERROR; } /*扫描块时要块对齐*/ addr_block_align = start - start%(spec.blocksize); /*得到要扫描的块长度*/ length_block_align = nandc_alige_size(start + length, spec.blocksize) - addr_block_align; /*如果没有分配内存就分配内存*/ if(!block_buf) { block_buf = (u32)himalloc(spec.blocksize); if(NULL == (void*)block_buf)//pclint 58 { NAND_TRACE(("nand_scan_bad: himalloc failed\n")); goto ERRO; } } /*还有块长度需要扫描*/ while(length_block_align > 0) { /*得到块号地址*/ blk_id = addr_block_align/spec.blocksize; if(NAND_OK != nand_isbad(blk_id, &is_bad)) { NAND_TRACE(("nand_scan_bad: nand_isbad failed\n")); goto ERRO; } if(NANDC_GOOD_BLOCK == is_bad) { times = 1; /*读整块数据如果没有出错的话表示是好坏*/ while((NANDC_E_READ == nand_read((FSZ)addr_block_align, block_buf, spec.blocksize, 0)) && (times)) { times--; } if(0 == times) { NAND_TRACE(("nand_scan_bad: find and read error, address:0x%x\n",addr_block_align)); ret = nand_bad(blk_id); if(ret) { NAND_TRACE(("nand_scan_bad:nand check bad failed, ret = 0x%x\n",ret)); } } /*是好块如果要擦除的话就擦除*/ else if(NANDC_TRUE == if_erase) { ret = nand_erase(blk_id); if(ret) { NAND_TRACE(("nand_scan_bad:nand erase failed, ret = 0x%x\n",ret)); } } else { } } else { NAND_TRACE(("nand_scan_bad:find bad block: 0x%x\n",addr_block_align)); } length_block_align -= spec.blocksize; addr_block_align += spec.blocksize; } return NAND_OK; ERRO: return NAND_ERROR; }
/********************************************************************************** * FUNC NAME: * ptable_parse_mtd_partitions() - external API: get mtd partitions from flash table * * PARAMETER: * @mtd_parts -[output] pointer to mtd partitions * @nr_parts - [output] number of mtd partitions * * * DESCRIPTION: * get mtd partitions from flash table * * CALL FUNC: * *********************************************************************************/ u32 ptable_parse_mtd_partitions(struct mtd_partition** mtd_parts, u32 *nr_parts) { struct ST_PART_TBL * ptable = NULL; struct mtd_partition *parts = NULL; u32 npart; u32 last_end = 0; u32 last_id = 0; if(!(mtd_parts && nr_parts)) { goto ERRO; } /*ensure that there's a ram table exist*/ /*lint -save -e539*/ ptable_ensure(); /*lint -restore*/ ptable_adapt(); #ifdef __FASTBOOT__ /*show all ptable info*/ #ifndef BSP_CONFIG_EDA ptable_show(NULL); #endif #endif ptable = ptable_get_ram_data(); /*get number of partitions*/ npart = 0; while(0 != strcmp(PTABLE_END_STR, ptable->name)) { if(ptable->capacity) /* skip empty part */ { npart++; } ptable++; } /*this memory never free */ parts = himalloc(sizeof(struct mtd_partition) * npart); if(NULL == parts) { hiout(("ptable_to_mtd_partition, error malloc\r\n")); goto ERRO; } memset(parts, 0x00 , (sizeof(struct mtd_partition) * npart)); /*lint -save -e613*/ *mtd_parts = parts; /*lint -restore*/ *nr_parts = npart; /*get address again*/ ptable = ptable_get_ram_data(); /*置0以后重新计算实际转移到MTD的分区数*/ npart = 0; /*form flash table to mtd partitions */ while(0 != strcmp(PTABLE_END_STR, ptable->name)) { /*not first partition (PTABLE_HEAD_STR)*/ if((last_end != ptable->offset) && (0 != last_id)) { hiout(("ptable check error! ")); hiout((ptable->name)); hiout(("\r\n")); goto ERRO; } #ifdef __KERNEL__ if(ptable->property & MOUNT_MTD){ #endif parts->name = ptable->name; parts->offset = ptable->offset; parts->size = ptable->capacity; parts++; npart++; #ifdef __KERNEL__ } #endif last_end = ptable->offset + ptable->capacity; last_id = ptable->image; ptable++; } *nr_parts = npart; return NANDC_OK; ERRO: if(NULL != parts) { hifree(parts); } return NANDC_ERROR; }