Пример #1
0
/**
 * 作用:得到nandflash相关规格参数的函数接口
 *
 * 参数:
 * @spec      ---把nandflash中的相关规格参数填写在此指针变量中去
 *
 *
 * 描述:得到nandflash的规格参数
 */
int bsp_get_nand_info(struct nand_spec *spec)
{
	struct nandc_host 	*host 		= nandc_nand_host;
	/*检查参数是否正确*/
	if(!host)
	{
	    NAND_TRACE(("ERROR: get nand info error.\n"));
	    goto erro;
	}

	if(!nand_isinit())
	{
	    NAND_TRACE(("ERROR: nandc driver not init yet!\n"));
	    goto erro;
	}
	/*复制nandflash的相关规格参数*/
	spec->pagesize 	 		= host->nandchip->spec.pagesize;
	spec->pagenumperblock	= (host->nandchip->spec.blocksize / spec->pagesize);
	spec->addrnum      		= host->nandchip->spec.addrcycle;
	spec->ecctype 	 		= host->nandchip->ecctype;
	spec->buswidth   		= host->nandchip->spec.buswidth;
	spec->blocksize         = host->nandchip->spec.blocksize;
	spec->sparesize         = host->nandchip->spec.sparesize;
	spec->chipsize          = host->nandchip->spec.chipsize;

	return NANDC_OK;
erro:
	return NANDC_ERROR;
}
Пример #2
0
/**
 * 作用:对nand标强制擦除
 *
 * 参数:
 * @blockid          ---block块的字符串
 *
 *
 * 描述:nand强制擦除功能,当如果有软件坏块时也可以用此函数来强制擦除
 */
void bsp_nand_erase_force(char *blockid)
{
    int ret = NANDC_ERROR;
    unsigned int id;

    char *blk_id = bsp_nand_argument_check(blockid);

    /* string to int  */
    ret= str2ul(blk_id, &id);
    if(ret)
    {
        NAND_TRACE(("[%s]ERROR: string to integer failed, ret = 0x%x.\n", __FUNCTION__, ret));
        goto ERRO;
    }

    /*直接擦除*/
    ret = nand_erase(id);
    if(ret)
    {
        NAND_TRACE(("[%s]ERROR: nand check bad failed, ret = 0x%x.\n", __FUNCTION__, ret));
        goto ERRO;
    }
    else
    {
        NAND_TRACE(("SUCCESS: erase block %x forcely.\n", id));
    }

    return;

ERRO:
    return;
}
Пример #3
0
/**
 * 作用:把字符串转换为数字
 *
 * 参数:
 * @str          ---要转换的字符串
 * @digit        ---得到的数字值
 *
 * 描述:把字符串转换为数字
 */
unsigned int str2ul(char *str, unsigned int *digit)
{
    int ret = NANDC_ERROR;
    unsigned int tmp_digit = 0;
    char *temp = str;

    /*参数不正确*/
    if(!str || !digit)
    {
        NAND_TRACE(("[%s]ERROR: input is NULL.\n", __FUNCTION__));
        goto ERRO;
    }

    /*把string转换为数字*/
    while(*temp != 0)
    {
        if(*temp < '0' || *temp > '9')
        {
            NAND_TRACE(("[%s]ERROR: string input is illegal.\n", __FUNCTION__));
            goto ERRO;
        }
        tmp_digit = tmp_digit * 10 + (*temp - '0');
        temp++;
    }

    *digit = tmp_digit;

    return NANDC_OK;

ERRO:
    return ret;
}
Пример #4
0
/**
 * 作用:擦除所有的yaffs文件系统分区
 *
 * 参数:
 * 无
 *
 *
 * 描述:擦除所有的yaffs文件系统分区,在升级的过程中使用,擦除所有的yaffs文件系统的分区
 */
void bsp_erase_yaffs_partitons(void)
{
    struct ST_PART_TBL * ptable = NULL;
    struct ptentry ptn;
    int ret = NANDC_ERROR;

    ptable_ensure();

    ptable = ptable_get_ram_data();
	/*遍历所有的分区信息*/
    while(0 != strcmp(PTABLE_END_STR, ptable->name))
    {
    	/*查找YAFFS文件系统的分区*/
        if(ptable->property & DATA_YAFFS)
        {
            /* coverity[buffer_size_warning] */
            strncpy(ptn.name, ptable->name, 16);
            ptn.start = ptable->offset;
            ptn.length = ptable->capacity;
            NAND_TRACE(("earsing %s, start 0x%x, length 0x%x\n", ptn.name, ptn.start, ptn.length));
            ret = flash_erase(&ptn);
            if(ret)
            {
                NAND_TRACE(("[%s] ERROR: erase %s failed, ret = %d\n", __FUNCTION__, ptn.name, ret));
                return;
            }
        }
        ptable++;
    }
}
Пример #5
0
/**
* 作用:读取分区相对偏移地址的标志值,主要是为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;
}
Пример #6
0
/**
 * 作用:打印nandflash相关规格参数的函数接口
 *
 * 输入参数:无
 *
 *
 * 描述:打印nand->spec 参数值
 */
void bsp_show_nand_info(void)
{
    struct nand_spec spec;
    if(NAND_ERROR == bsp_get_nand_info(&spec))
    {
        NAND_TRACE(("ERROR: nand get spec error.\n"));
        return;
    }
    NAND_TRACE((" ------begin show nand info----------\n"));
    NAND_TRACE((" chipsize=%dMB,blocksize=%dKB,pagesize=%dKB,sparesize=%d\n",
    	                   (spec.chipsize/1024/1024),spec.blocksize/1024,spec.pagesize/1024,spec.sparesize));
    NAND_TRACE((" pagenumperblock=%d,ecctype=%d,buswidth=%d,addrnum=%d\n",
    	                   spec.pagenumperblock,spec.ecctype,(0==spec.buswidth?8:16),spec.addrnum));
    NAND_TRACE((" ------end  show nand info----------\n"));
}
Пример #7
0
/**
* 作用:nandc模块提供对外通过分区名来查找分区表的函数接口
*
* 参数:
* @partition_name     ---分区表的名
* 描述:通过分区名返回分区表信息,查找成功返回分区表指针,查找不成功返回NULL
*
*/
struct ST_PART_TBL * find_partition_by_name(const char *partition_name)
{
	struct ST_PART_TBL * ptable = NULL;

	ptable_ensure();

	ptable = ptable_get_ram_data();

	/*遍历所有的分区表信息*/
	while(0 != strcmp(PTABLE_END_STR, ptable->name))
	{
		/*查找到就退出*/
	    if(0 == strcmp(partition_name, ptable->name))
	    {
	        break;
	    }
	    ptable++;
	}
	/*如果不为空就表示查找得所要的分区表信息*/
	if(0 == strcmp(PTABLE_END_STR, ptable->name))
	{
		NAND_TRACE(("ERROR: can't find partition %s, function %s\n", partition_name, __FUNCTION__));
	    return NULL;
	}

	return ptable;

}
Пример #8
0
/**
* 作用:nandc模块按分区名和分区偏移地址来擦除flash操作
*
* 参数:
* @partition_name          		---要擦除的分区名
* @partition_offset      	    ---要擦除的相对偏移地址
*
*
* 描述:根据分区名和分区的偏移地址来确定Flash的地址,再来擦除一个block,注意是擦除一个block数据块
*/
int bsp_nand_erase(const char *partition_name, u32 partition_offset)
{
    u32 flash_addr;
    u32 block_id, bad_flag;
    u32 ret = NANDC_ERROR;
	struct nandc_host  * host   = NULL;
    struct ST_PART_TBL * ptable = find_partition_by_name(partition_name);
	/*参数不正确*/
    if(!ptable)
    {
        goto ERRO;
    }

    /*得到flash的地址信息*/
    flash_addr = ptable->offset + partition_offset;

    host = nandc_nand_host;
    if(!host)
    {
        NAND_TRACE(("ERROR: function %s, line %d\n", __FUNCTION__, __LINE__));
        goto ERRO;
    }

    /*得到块号并判断是否是坏块*/
    block_id = flash_addr / host->nandchip->spec.blocksize;
    ret = nand_isbad(block_id, &bad_flag);
    if(ret)
    {
        NAND_TRACE(("ERROR: nand quary bad failed, function %s, line %d\n", __FUNCTION__, __LINE__));
        goto ERRO;
    }

    if(NANDC_BAD_BLOCK == bad_flag)
    {
        NAND_TRACE(("ERROR: try to erase a bad block, function %s, line %d\n", __FUNCTION__, __LINE__));
        goto ERRO;
    }
	/*擦除flash操作*/
	return nand_erase(block_id);

ERRO:
    return ret;
}
Пример #9
0
/**
* 作用:nandc模块提供对外初始化nandc控制器的函数接口
*
* 参数:
* 无
* 描述:初始化nandc控制器的数据结构并调用底层的nandc硬件控制器的初始化函数
*
*/
u32 nand_init(void)
{
	struct nand_bus* handle = NULL;
	u32 result = NAND_ERROR;

	handle = &nand_handle;
	/*如果已经初始化完成了就直接退出来*/
	if(NAND_INIT_MAGIC == handle->init_flag)
	{
		result = NAND_OK;
		NAND_TRACE(("!!nand module already  inited!!\n"));
		goto EXIT;
	}

	memset((void*)handle, 0x00, sizeof(nand_handle));

	/*指向具体的操作nandflash的操作函数,当下面操作具体的nandflash的函数发生了变化时,可以保证对上面提供函数接口不变*/
	handle->funcs  =  &nandc_nand_funcs;

	/*nandflash硬件控制器的具体初始化函数*/
	if(handle->funcs->init)
	{
		result = handle->funcs->init();
	}
	else
	{
		NAND_TRACE(("ERRO!!nand module init is NULL\n"));
		result = NAND_ERROR;
	}
	/*初始化完成后设置标志位*/
	if(NAND_OK == result)
	{
		handle->init_flag = NAND_INIT_MAGIC;
	}
	else
	{
		NAND_TRACE(("ERRO!!nand module init failed\n"));
	}

EXIT:
	return result;

}
Пример #10
0
/**
 * 作用:对nand标坏块
 *
 * 参数:
 * @blockid          ---block块的字符串
 *
 *
 * 描述:nand标坏块
 */
void bsp_nand_markbad(char *blockid)
{
    int ret = NANDC_ERROR;
    unsigned int id, bad_flag;
    char *blk_id = bsp_nand_argument_check(blockid);

    /* string to int  */
    ret= str2ul(blk_id, &id);
    if(ret)
    {
        NAND_TRACE(("ERROR: string to integer failed, ret = 0x%x.\n", ret));
        goto EXIT;
    }

    /* check block bad. if good, mark bad; else return */
    ret = nand_isbad(id, &bad_flag);
    if(ret)
    {
        NAND_TRACE(("[%s]ERROR: nand check bad failed, ret = 0x%x.\n", __FUNCTION__, ret));
        goto EXIT;
    }

    if(NANDC_GOOD_BLOCK == bad_flag)
    {
        ret = nand_bad(id);
        if(ret)
        {
            NAND_TRACE(("[%s]ERROR: nand mark bad failed, ret = 0x%x.\n", __FUNCTION__, ret));
            goto EXIT;
        }
    }
    else
    {
        NAND_TRACE(("[%s]WARNING: block 0x%x is already bad.\n", __FUNCTION__));
        goto EXIT;
    }

    return;

EXIT:
    return;
}
Пример #11
0
/**
* 作用:nandc模块提供对外得到nandflash相关规格参数的函数接口
*
* 参数:
* @spec      ---把nandflash中的相关参数填写在此指针变量中去
*
* 描述:得到nandflash的规格参数
*/
u32 nand_get_spec(struct nand_spec *spec)
{
    struct nand_bus* handle;
    struct nand_interface * nandfuncs;

    handle = &nand_handle;
	/*如果没有初始化就返回错误*/
    if(NAND_INIT_MAGIC != handle->init_flag)
    {
        NAND_TRACE(("error!! balong nand not inited\n"));
        return NAND_ERROR;
    }

    nandfuncs = handle->funcs;
	/*得到flash的规格参数*/
    if(nandfuncs->get_spec)
    {
        return  nandfuncs->get_spec(spec);
    }
	/*走到这里就说明有错误了走错误流程了*/
    NAND_TRACE(("error!! get_spec not inited\n"));
    return NAND_ERROR;
}
Пример #12
0
/**
* 作用:nandc模块按分区名和分区相对偏移来确定此块是不是坏块
*
* 参数:
* @partition_name          		---查询数据块的分区名
* @partition_offset      	    ---查询数据块的分区相对偏移地址
*
* 描述:根据分区名和分区的偏移地址来确定Flash的地址,再来判断此block是不是坏块
返回值:
* 0表示此块是好块
* 1表示是坏块
* 其他的表示有错误
*/
int bsp_nand_isbad(const char *partition_name, u32 partition_offset)
{
    u32 flash_addr;
    u32 bad_flag;
    u32 ret = NANDC_ERROR;
	struct nandc_host  * host   = NULL;
    struct ST_PART_TBL * ptable = find_partition_by_name(partition_name);

    if(!ptable)
    {
        goto ERRO;
    }

    /*得到Flash地址*/
    flash_addr = ptable->offset + partition_offset;

    host = nandc_nand_host;
    if(!host)
    {
        NAND_TRACE(("ERROR: function %s, line %d\n", __FUNCTION__, __LINE__));
        goto ERRO;
    }
	/*判断此block是否是坏块*/
	ret = nand_isbad(flash_addr / host->nandchip->spec.blocksize, &bad_flag);
    if(ret == 1)
    {
        return -6;
    }
    else if(ret > 1)
    {
        return ret;
    }

    if(bad_flag == 1)  /* bad block */
    {
        return 1;
    }
    else               /* good block */
    {
        return 0;
    }

ERRO:
    return ret;
}
Пример #13
0
/**
 * \brief Writes the data and/or spare area of a NANDFLASH page, after calculating an
 * ECC for the data area and storing it in the spare. If no data buffer is
 * provided, the ECC is read from the existing page spare. If no spare buffer
 * is provided, the spare area is still written with the ECC information
 * calculated on the data buffer.
 * \param nand Pointer to an EccNandFlash instance.
 * \param block  Number of the block to write in.
 * \param page  Number of the page to write inside the given block.
 * \param data  Data area buffer, can be 0.
 * \param spare  Spare area buffer, can be 0.
 * \return 0 if successful; otherwise returns an error code.
 */
uint8_t nand_ecc_write_page(const struct _nand_flash *nand,
	uint16_t block, uint16_t page, void *data, void *spare)
{
	NAND_TRACE("nand_ecc_write_page(B#%d:P#%d)\r\n", block, page);
	assert(data || spare);

	if (nand_is_using_pmecc()) {
		if (spare)
			return NAND_ERROR_ECC_NOT_COMPATIBLE;
		return ecc_write_page_with_pmecc(nand, block, page, data);
	}

	if (nand_is_using_software_ecc())
		return ecc_write_page_with_swecc(nand, block, page, data, spare);

	if (nand_is_using_no_ecc())
		return nand_raw_write_page(nand, block, page, data, spare);

	return NAND_ERROR_ECC_NOT_COMPATIBLE;
}
Пример #14
0
/******************************************************************************************
 * FUNC NAME:
 * @bsp_update_size_of_lastpart() - external API:
 *
 * PARAMETER:
 * @new_ptable - addr of new ptable
 *
 * RETURN:
 *    null
 *
 * DESCRIPTION:
 *    update the size of last partition to shared memory
 *    分区表最后一个分区将flash最后一块空间完全占有,从而导致静态编译的ptable.bin与软件实际使用的ptable不一样,
 *    升级分区表的时候就认为两个分区不一样,从而导致对yaffs分区的擦除。此处用实际使用的分区表最后一个分区大小
 *    覆盖新ptable最后分区大小
 *
 * CALL FUNC:
 *
 *****************************************************************************************/
void bsp_update_size_of_lastpart(struct ST_PART_TBL *new_ptable)
{
    struct ST_PART_TBL * old_ptable = NULL;
    if(!new_ptable)
    {
        NAND_TRACE(("[%s]argu error\n", __FUNCTION__));
        return;
    }

    /*根据分区名得到分区数据结构*/
    while(0 != strcmp(PTABLE_END_STR, new_ptable->name))
    {
        new_ptable++;
    }

    new_ptable--;

    old_ptable = find_partition_by_name(new_ptable->name);
    if(old_ptable)
    {
        new_ptable->capacity = old_ptable->capacity;
    }

}
Пример #15
0
/**
 * 作用: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;
}
Пример #16
0
/**
* 作用:nandc模块所有函数功能通用实现过程
*
* 参数:
* @param          ---包含了要操作nandflash的具体参数信息
* @func_type      ---函数的类型,根据此值知道要实现什么功能(读,写)
*
*
* 描述:所有的函数功能都是通过这个函数来处理,通过func_type来确定是要实现什么功能,直接调用具体的函数指针来
* 执行具体的操作,当需要增加新的函数功能时,就在此通过处理流程中增加相关的流程就行,方便后面功能的扩展
*
*/
u32 nand_run(struct nand_param* param, u32 func_type)
{
	struct nand_bus* handle;
	struct nand_interface * nandfuncs;
	u32 result = NAND_OK;

	handle = &nand_handle;
	/*判断是否初始化成功*/
	if(NAND_INIT_MAGIC != handle->init_flag)
	{
		NAND_TRACE(("error!! balong nand not inited\n"));
		return NAND_ERROR;
	}
	/*得到具体的操作的函数指针*/
	nandfuncs = handle->funcs;

	switch (func_type)
	{
		case READ_NAND:
		{
			/*使能ECC功能的读Flash操作*/
			if(nandfuncs->read)
			{
				result = nandfuncs->read(param->addr_flash,
			                         param->addr_data,
			                         param->size_data,
			                         param->size_oob,
			                         param->skip_length);
			}
			else
			{
				NAND_TRACE(("error!! func read_random is NULL\n"));
				result = NAND_ERROR;
			}
		}
		break;

		case READ_RAW:
		{
			/*不使能ECC功能的裸读Flash操作*/
			if(nandfuncs->read_page_raw)
			{
				result = nandfuncs->read_page_raw(param->number,
			                                  (u32)param->addr_flash,
			                                  (u32)param->addr_data,
			                                       param->size_data);
			}
			else
			{
				NAND_TRACE(("error!! func read_page_yaffs is NULL\n"));
				result = NAND_ERROR;
			}
		}
		break;

		case QUARY_BAD:
		{
			/*查询坏块的功能函数*/
			if(nandfuncs->quary_bad)
			{
				result = nandfuncs->quary_bad(param->number, (u32*)param->addr_data);
			}
			else
			{
				NAND_TRACE(("error!! func quary_bad is NULL\n"));
				result = NAND_ERROR;
			}
		}
		break;

		case ERASE_BLOCK:
		{
			/*擦除数据块的功能函数*/
			if(nandfuncs->erase_by_id)
			{
				result = nandfuncs->erase_by_id(param->number);
			}
			else
			{
				NAND_TRACE(("error!! func erase_by_id is NULL\n"));
				result = NAND_ERROR;
			}
		}
		break;

		case WRITE_NAND:
		{
			/*使能ECC功能的写Flash操作,注意write中会自已先擦除Flash再来写,所有用户就不用在写之前擦除了*/
			if(nandfuncs->write)
			{
				result = nandfuncs->write(param->addr_flash,
			                          	  param->addr_data,
			                              param->size_data,
			                              param->size_oob,
			                              param->skip_length);
			}
			else
			{
				NAND_TRACE(("error!! func write flash is NULL\n"));
				result = NAND_ERROR;
			}
		}
		break;

		case WRITE_RAW:
		{
			/*不使能ECC功能的裸写Flash操作*/
			if(nandfuncs->write_page_raw)
			{
				result = nandfuncs->write_page_raw(param->number,
			                                    (u32)param->addr_flash,
			                                    (u32)param->addr_data,
			                                    param->size_data);
			}
			else
			{
				NAND_TRACE(("error!! func write_page_raw is NULL\n"));
				result = NAND_ERROR;
			}
		}
		break;

		case MARK_BAD:
		{
			/*标坏块的功能*/
			if(nandfuncs->mark_bad)
			{
				result = nandfuncs->mark_bad(param->number );
			}
			else
			{
				NAND_TRACE(("error!! func mark_bad is NULL\n"));
				result = NAND_ERROR;
			}
		}
		break;
		default:
			NAND_TRACE(("ERRO!! nand function type:%d not defined\n",func_type));
			result = NAND_ERROR;
		break;
	}
	/*返回操作的结果,0表示操作成功,1表示操作失败*/
	return result;
}