/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& * Function: emu_Read_Page_Main_Spare * Inputs: Write Buffer * Address * Buffer size * Outputs: PASS=0 (notice 0=ok here) * Description: Read from flash main+spare area * *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ u16 emu_Read_Page_Main_Spare(u8 *read_data, u32 Block, u16 Page, u16 PageCount) { int i; nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); if (Block >= DeviceInfo.wTotalBlocks) { printk(KERN_ERR "Read Page Main+Spare " "Error: Block Address too big\n"); return FAIL; } if (Page + PageCount > DeviceInfo.wPagesPerBlock) { printk(KERN_ERR "Read Page Main+Spare " "Error: Page number too big\n"); return FAIL; } nand_dbg_print(NAND_DBG_DEBUG, "Read Page Main + Spare - " "No. of pages %u block %u start page %u\n", (unsigned int)PageCount, (unsigned int)Block, (unsigned int)Page); for (i = 0; i < PageCount; i++) { if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { memset(read_data, 0xFF, DeviceInfo.wPageSize); } else { memcpy(read_data, (u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]), DeviceInfo.wPageSize); } read_data += DeviceInfo.wPageSize; Page++; } return PASS; }
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& * Function: mtd_Flash_Release * Inputs: none * Outputs: PASS=0 (notice 0=ok here) * Description: Releases the flash. * *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ int mtd_Flash_Release(void) { nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); if (!spectra_mtd) return PASS; put_mtd_device(spectra_mtd); spectra_mtd = NULL; return PASS; }
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& * Function: mtd_Read_Page_Main * Inputs: Read buffer address pointer * Block number * Page number * Number of pages to process * Outputs: PASS=0 (notice 0=ok here) * Description: Read the data from the flash main area to the buffer * *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ u16 mtd_Read_Page_Main(u8 *read_data, u32 Block, u16 Page, u16 PageCount) { size_t retlen; int ret = 0; nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); if (Block >= DeviceInfo.wTotalBlocks) return FAIL; if (Page + PageCount > DeviceInfo.wPagesPerBlock) return FAIL; nand_dbg_print(NAND_DBG_DEBUG, "mtd_Read_Page_Main: " "lba %u Page %u PageCount %u\n", (unsigned int)Block, (unsigned int)Page, (unsigned int)PageCount); while (PageCount) { ret = spectra_mtd->read(spectra_mtd, (Block * spectra_mtd->erasesize) + (Page * spectra_mtd->writesize), DeviceInfo.wPageDataSize, &retlen, read_data); if (ret) { printk(KERN_ERR "%s failed %d\n", __func__, ret); return FAIL; } read_data += DeviceInfo.wPageDataSize; Page++; PageCount--; } nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); return PASS; }
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& * Function: mtd_Erase_Block * Inputs: Address * Outputs: PASS=0 (notice 0=ok here) * Description: Erase a block * *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ u16 mtd_Erase_Block(u32 block_add) { struct erase_info erase; DECLARE_COMPLETION_ONSTACK(comp); int ret; nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); if (block_add >= DeviceInfo.wTotalBlocks) { printk(KERN_ERR "mtd_Erase_Block error! " "Too big block address: %d\n", block_add); return FAIL; } nand_dbg_print(NAND_DBG_DEBUG, "Erasing block %d\n", (int)block_add); erase.mtd = spectra_mtd; erase.callback = erase_callback; erase.addr = block_add * spectra_mtd->erasesize; erase.len = spectra_mtd->erasesize; erase.priv = (unsigned long)∁ ret = spectra_mtd->erase(spectra_mtd, &erase); if (!ret) { wait_for_completion(&comp); if (erase.state != MTD_ERASE_DONE) ret = -EIO; } if (ret) { printk(KERN_WARNING "mtd_Erase_Block error! " "erase of region [0x%llx, 0x%llx] failed\n", erase.addr, erase.len); return FAIL; } return PASS; }
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& * Function: emu_Write_Page_Main_Spare * Inputs: Write buffer * address * buffer length * Outputs: PASS=0 (notice 0=ok here) * Description: Write the buffer to main+spare area of flash * *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ u16 emu_Write_Page_Main_Spare(u8 *write_data, u32 Block, u16 Page, u16 page_count) { u16 i; nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); if (Block >= DeviceInfo.wTotalBlocks) { printk(KERN_ERR "Write Page Main + Spare " "Error: Block Address too big\n"); return FAIL; } if (Page + page_count > DeviceInfo.wPagesPerBlock) { printk(KERN_ERR "Write Page Main + Spare " "Error: Page number too big\n"); return FAIL; } nand_dbg_print(NAND_DBG_DEBUG, "Write Page Main+Spare - " "No. of pages %u block %u start page %u\n", (unsigned int)page_count, (unsigned int)Block, (unsigned int)Page); for (i = 0; i < page_count; i++) { if (NULL == flash_memory[Block * GLOB_LLD_PAGES + Page]) { printk(KERN_ERR "Run out of memory!\n"); return FAIL; } memcpy((u8 *) (flash_memory[Block * GLOB_LLD_PAGES + Page]), write_data, DeviceInfo.wPageSize); write_data += DeviceInfo.wPageSize; Page++; } return PASS; }
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& * Function: mtd_Flash_Init * Inputs: none * Outputs: PASS=0 (notice 0=ok here) * Description: Creates & initializes the flash RAM array. * *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ u16 mtd_Flash_Init(void) { if (mtddev == -1) { printk(KERN_ERR "No MTD device specified. Give mtddev parameter\n"); return FAIL; } spectra_mtd = get_mtd_device(NULL, mtddev); if (!spectra_mtd) { printk(KERN_ERR "Failed to obtain MTD device #%d\n", mtddev); return FAIL; } nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); return PASS; }
u16 mtd_Read_Device_ID(void) { uint64_t tmp; nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); if (!spectra_mtd) return FAIL; DeviceInfo.wDeviceMaker = 0; DeviceInfo.wDeviceType = 8; DeviceInfo.wSpectraStartBlock = SPECTRA_START_BLOCK; tmp = spectra_mtd->size; do_div(tmp, spectra_mtd->erasesize); DeviceInfo.wTotalBlocks = tmp; DeviceInfo.wSpectraEndBlock = DeviceInfo.wTotalBlocks - 1; DeviceInfo.wPagesPerBlock = spectra_mtd->erasesize / spectra_mtd->writesize; DeviceInfo.wPageSize = spectra_mtd->writesize + spectra_mtd->oobsize; DeviceInfo.wPageDataSize = spectra_mtd->writesize; DeviceInfo.wPageSpareSize = spectra_mtd->oobsize; DeviceInfo.wBlockSize = DeviceInfo.wPageSize * DeviceInfo.wPagesPerBlock; DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * DeviceInfo.wPagesPerBlock; DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock + 1); DeviceInfo.MLCDevice = 0;//spectra_mtd->celltype & NAND_CI_CELLTYPE_MSK; DeviceInfo.nBitsInPageNumber = (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); DeviceInfo.nBitsInPageDataSize = (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); DeviceInfo.nBitsInBlockDataSize = (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); #if CMD_DMA totalUsedBanks = 4; valid_banks[0] = 1; valid_banks[1] = 1; valid_banks[2] = 1; valid_banks[3] = 1; #endif return PASS; }
u16 emu_Read_Device_ID(void) { nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); DeviceInfo.wDeviceMaker = 0; DeviceInfo.wDeviceType = 8; DeviceInfo.wSpectraStartBlock = 36; DeviceInfo.wSpectraEndBlock = GLOB_LLD_BLOCKS - 1; DeviceInfo.wTotalBlocks = GLOB_LLD_BLOCKS; DeviceInfo.wPagesPerBlock = GLOB_LLD_PAGES; DeviceInfo.wPageSize = GLOB_LLD_PAGE_SIZE; DeviceInfo.wPageDataSize = GLOB_LLD_PAGE_DATA_SIZE; DeviceInfo.wPageSpareSize = GLOB_LLD_PAGE_SIZE - GLOB_LLD_PAGE_DATA_SIZE; DeviceInfo.wBlockSize = DeviceInfo.wPageSize * GLOB_LLD_PAGES; DeviceInfo.wBlockDataSize = DeviceInfo.wPageDataSize * GLOB_LLD_PAGES; DeviceInfo.wDataBlockNum = (u32) (DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock + 1); DeviceInfo.MLCDevice = 1; /* Emulate MLC device */ DeviceInfo.nBitsInPageNumber = (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPagesPerBlock); DeviceInfo.nBitsInPageDataSize = (u8)GLOB_Calc_Used_Bits(DeviceInfo.wPageDataSize); DeviceInfo.nBitsInBlockDataSize = (u8)GLOB_Calc_Used_Bits(DeviceInfo.wBlockDataSize); #if CMD_DMA totalUsedBanks = 4; valid_banks[0] = 1; valid_banks[1] = 1; valid_banks[2] = 1; valid_banks[3] = 1; #endif return PASS; }
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& * Function: emu_Enable_Disable_Interrupts * Inputs: enable or disable * Outputs: none * Description: NOP *&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/ void emu_Enable_Disable_Interrupts(u16 INT_ENABLE) { nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); }
/* Read nand emu file and then fill it's content to flash_memory */ int emu_load_file_to_mem(void) { mm_segment_t fs; struct file *nef_filp = NULL; struct inode *inode = NULL; loff_t nef_size = 0; loff_t tmp_file_offset, file_offset; ssize_t nread; int i, rc = -EINVAL; nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n", __FILE__, __LINE__, __func__); fs = get_fs(); set_fs(get_ds()); nef_filp = filp_open("/root/nand_emu_file", O_RDWR | O_LARGEFILE, 0); if (IS_ERR(nef_filp)) { printk(KERN_ERR "filp_open error: " "Unable to open nand emu file!\n"); return PTR_ERR(nef_filp); } if (nef_filp->f_path.dentry) { inode = nef_filp->f_path.dentry->d_inode; } else { printk(KERN_ERR "Can not get valid inode!\n"); goto out; } nef_size = i_size_read(inode->i_mapping->host); if (nef_size <= 0) { printk(KERN_ERR "Invalid nand emu file size: " "0x%llx\n", nef_size); goto out; } else { nand_dbg_print(NAND_DBG_DEBUG, "nand emu file size: %lld\n", nef_size); } file_offset = 0; for (i = 0; i < GLOB_LLD_BLOCKS * GLOB_LLD_PAGES; i++) { tmp_file_offset = file_offset; nread = vfs_read(nef_filp, (char __user *)flash_memory[i], GLOB_LLD_PAGE_SIZE, &tmp_file_offset); if (nread < GLOB_LLD_PAGE_SIZE) { printk(KERN_ERR "%s, Line %d - " "nand emu file partial read: " "%d bytes\n", __FILE__, __LINE__, (int)nread); goto out; } file_offset += GLOB_LLD_PAGE_SIZE; } rc = 0; out: filp_close(nef_filp, current->files); set_fs(fs); return rc; }