Пример #1
0
int VFL_Read(uint32_t virtualPageNumber, uint8_t* buffer, uint8_t* spare, int empty_ok, int* refresh_page) {
	if(refresh_page) {
		*refresh_page = FALSE;
	}

	VFLData1.field_8++;
	VFLData1.field_20++;

	uint32_t dwVpn = virtualPageNumber + (Data->pagesPerSubBlk * Data2->field_4);
	if(dwVpn >= Data->pagesTotal) {
		bufferPrintf("ftl: dwVpn overflow: %d\r\n", dwVpn);
		return ERROR_ARG;
	}

	if(dwVpn < Data->pagesPerSubBlk) {
		bufferPrintf("ftl: dwVpn underflow: %d\r\n", dwVpn);
	}

	uint16_t virtualBank;
	uint16_t virtualBlock;
	uint16_t virtualPage;
	uint16_t physicalBlock;

	virtual_page_number_to_virtual_address(dwVpn, &virtualBank, &virtualBlock, &virtualPage);
	physicalBlock = virtual_block_to_physical_block(virtualBank, virtualBlock);

	int page = physicalBlock * Data->pagesPerBlock + virtualPage;

	int ret = nand_read(virtualBank, page, buffer, spare, TRUE, TRUE);

	if(!empty_ok && ret == ERROR_EMPTYBLOCK) {
		ret = ERROR_NAND;
	}

	if(refresh_page) {
		if((Data->field_2F <= 0 && ret == 0) || ret == ERROR_NAND) {
			bufferPrintf("ftl: setting refresh_page to TRUE due to the following factors: Data->field_2F = %x, ret = %d\r\n", Data->field_2F, ret);
			*refresh_page = TRUE;
		}
	}

	if(ret == ERROR_ARG || ret == ERROR_NAND) {
		nand_bank_reset(virtualBank, 100);
		ret = nand_read(virtualBank, page, buffer, spare, TRUE, TRUE);
		if(!empty_ok && ret == ERROR_EMPTYBLOCK) {
			return ERROR_NAND;
		}

		if(ret == ERROR_ARG || ret == ERROR_NAND)
			return ret;
	}

	if(ret == ERROR_EMPTYBLOCK) {
		if(spare) {
			memset(spare, 0xFF, sizeof(SpareData));
		}
	}

	return ret;
}
Пример #2
0
int VFL_Read(u32 virtualPageNumber, u8* buffer, u8* spare, bool empty_ok)
{
	u16 virtualBank;
	u16 virtualBlock;
	u16 virtualPage;
	u16 physicalBlock;
	u32 dwVpn;

	int page;
	int ret;

	VFLData1.field_8++;
	VFLData1.field_20++;

	dwVpn = virtualPageNumber + (NANDGeometry->pagesPerSuBlk * FTLData->field_4);
	if(dwVpn >= NANDGeometry->pagesTotal) {
		LOG("ftl: dwVpn overflow: %d\n", dwVpn);
		return -EINVAL;
	}

	if(dwVpn < NANDGeometry->pagesPerSuBlk) {
		LOG("ftl: dwVpn underflow: %d\n", dwVpn);
	}

	virtual_page_number_to_virtual_address(dwVpn, &virtualBank, &virtualBlock, &virtualPage);
	physicalBlock = virtual_block_to_physical_block(virtualBank, virtualBlock);

	page = physicalBlock * NANDGeometry->pagesPerBlock + virtualPage;

#ifdef IPHONE_DEBUG
	LOG("ftl: vfl_read: vpn: %u, bank %d, page %u\n", virtualPageNumber, virtualBank, page);
#endif

	ret = nand_read(virtualBank, page, buffer, spare, true, true);

	if(!empty_ok && ret == ERROR_EMPTYBLOCK)
	{
		ret = -EIO;
	}

	if(ret == -EINVAL || ret == -EIO) {
		nand_bank_reset(virtualBank, 100);
		ret = nand_read(virtualBank, page, buffer, spare, true, true);
		if(!empty_ok && ret == ERROR_EMPTYBLOCK) {
			return -EIO;
		}

		if(ret == -EINVAL || ret == -EIO)
			return ret;
	}

	if(ret == ERROR_EMPTYBLOCK) {
		if(spare) {
			memset(spare, 0xFF, sizeof(SpareData));
		}
	}

	return ret;
}
Пример #3
0
int nand_setup() {
	if(HasNANDInit)
		return 0;

	NANDSetting1 = 7;
	NANDSetting2 = 7;
	NANDSetting3 = 7;
	NANDSetting4 = 7;

	bufferPrintf("nand: Probing flash controller...\r\n");

	clock_gate_switch(NAND_CLOCK_GATE1, ON);
	clock_gate_switch(NAND_CLOCK_GATE2, ON);

	int bank;
	for(bank = 0; bank < NAND_NUM_BANKS; bank++) {
		banksTable[bank] = bank;
	}

	NumValidBanks = 0;
	const NANDDeviceType* nandType = NULL;

	SET_REG(NAND + NAND_SETUP, 0);
	SET_REG(NAND + NAND_SETUP, GET_REG(NAND + NAND_SETUP) | (ECCType << 4));

	for(bank = 0; bank < NAND_NUM_BANKS; bank++) {
		nand_bank_reset(bank, 100);

		SET_REG(NAND + NAND_CON, NAND_CON_SETTING1);
		SET_REG(NAND + NAND_CONFIG,
			((NANDSetting1 & NAND_CONFIG_SETTING1MASK) << NAND_CONFIG_SETTING1SHIFT) | ((NANDSetting2 & NAND_CONFIG_SETTING2MASK) << NAND_CONFIG_SETTING2SHIFT)
			| (1 << (banksTable[bank] + 1)) | NAND_CONFIG_DEFAULTS);

		SET_REG(NAND + NAND_CMD, NAND_CMD_ID);

		wait_for_ready(500);

		SET_REG(NAND + NAND_CONFIG4, 0);
		SET_REG(NAND + NAND_CONFIG3, 0);
		SET_REG(NAND + NAND_CON, NAND_CON_ADDRESSDONE);

		wait_for_address_complete(500);
		nand_bank_reset_helper(bank, 100);

		SET_REG(NAND + NAND_TRANSFERSIZE, 8);
		SET_REG(NAND + NAND_CON, NAND_CON_BEGINTRANSFER);

		wait_for_status_bit_3(500);
		uint32_t id = GET_REG(NAND + NAND_DMA_SOURCE);
		const NANDDeviceType* candidate = SupportedDevices;
		while(candidate->id != 0) {
			if(candidate->id == id) {
				if(nandType == NULL) {
					nandType = candidate;
				} else if(nandType != candidate) {
					bufferPrintf("nand: Mismatched device IDs (0x%08x after 0x%08x)\r\n", id, nandType->id);
					return ERROR_ARG;
				}
				banksTable[NumValidBanks++] = bank;
			}
			candidate++;
		}

		SET_REG(NAND + NAND_CON, NAND_CON_SETTING1);
	}

	if(nandType == NULL) {
		bufferPrintf("nand: No supported NAND found\r\n");
		return ERROR_ARG;
	}

	Data.DeviceID = nandType->id;
	Data.banksTable = banksTable;

	NANDSetting2 = (((clock_get_frequency(FrequencyBaseBus) * (nandType->NANDSetting2 + 1)) + 99999999)/100000000) - 1;
	NANDSetting1 = (((clock_get_frequency(FrequencyBaseBus) * (nandType->NANDSetting1 + 1)) + 99999999)/100000000) - 1;
	NANDSetting3 = (((clock_get_frequency(FrequencyBaseBus) * (nandType->NANDSetting3 + 1)) + 99999999)/100000000) - 1;
	NANDSetting4 = (((clock_get_frequency(FrequencyBaseBus) * (nandType->NANDSetting4 + 1)) + 99999999)/100000000) - 1;

	if(NANDSetting2 > 7)
		NANDSetting2 = 7;

	if(NANDSetting1 > 7)
		NANDSetting1 = 7;

	if(NANDSetting3 > 7)
		NANDSetting3 = 7;

	if(NANDSetting4 > 7)
		NANDSetting4 = 7;

	Data.blocksPerBank = nandType->blocksPerBank;
	Data.banksTotal = NumValidBanks;
	Data.sectorsPerPage = nandType->sectorsPerPage;
	Data.userSubBlksTotal = nandType->userSubBlksTotal;
	Data.bytesPerSpare = nandType->bytesPerSpare;
	Data.field_2E = 4;
	Data.field_2F = 3;
	Data.pagesPerBlock = nandType->pagesPerBlock;

	if(Data.sectorsPerPage > 4) {
		LargePages = TRUE;
	} else {
		LargePages = FALSE;
	}

	if(nandType->ecc1 == 6) {
		ECCType = 4;
		TotalECCDataSize = Data.sectorsPerPage * 15;
	} else if(nandType->ecc1 == 8) {
		ECCType = 8;
		TotalECCDataSize = Data.sectorsPerPage * 20;
	} else if(nandType->ecc1 == 4) {
		ECCType = 0;
		TotalECCDataSize = Data.sectorsPerPage * 10;
	}

	if(nandType->ecc2 == 6) {
		ECCType2 = 4;
	} else if(nandType->ecc2 == 8) {
		ECCType2 = 8;
	} else if(nandType->ecc2 == 4) {
		ECCType2 = 0;
	}

	Data.field_4 = 5;
	Data.bytesPerPage = SECTOR_SIZE * Data.sectorsPerPage;
	Data.pagesPerBank = Data.pagesPerBlock * Data.blocksPerBank;
	Data.pagesTotal = Data.pagesPerBank * Data.banksTotal;
	Data.pagesPerSubBlk = Data.pagesPerBlock * Data.banksTotal;
	Data.userPagesTotal = Data.userSubBlksTotal * Data.pagesPerSubBlk;
	Data.subBlksTotal = (Data.banksTotal * Data.blocksPerBank) / Data.banksTotal;

	Data2.field_2 = Data.subBlksTotal - Data.userSubBlksTotal - 28;
	Data2.field_0 = Data2.field_2 + 4;
	Data2.field_4 = Data2.field_2 + 5;
	Data2.field_6 = 3;
	Data2.field_8 = 23;
	if(Data2.field_8 == 0)
		Data.field_22 = 0;

	int bits = 0;
	int i = Data2.field_8;
	while((i <<= 1) != 0) {
		bits++;
	}

	Data.field_22 = bits;

	bufferPrintf("nand: DEVICE: %08x\r\n", Data.DeviceID);
	bufferPrintf("nand: BANKS_TOTAL: %d\r\n", Data.banksTotal);
	bufferPrintf("nand: BLOCKS_PER_BANK: %d\r\n", Data.blocksPerBank);
	bufferPrintf("nand: SUBLKS_TOTAL: %d\r\n", Data.subBlksTotal);
	bufferPrintf("nand: USER_SUBLKS_TOTAL: %d\r\n", Data.userSubBlksTotal);
	bufferPrintf("nand: PAGES_PER_SUBLK: %d\r\n", Data.pagesPerSubBlk);
	bufferPrintf("nand: PAGES_PER_BANK: %d\r\n", Data.pagesPerBank);
	bufferPrintf("nand: SECTORS_PER_PAGE: %d\r\n", Data.sectorsPerPage);
	bufferPrintf("nand: BYTES_PER_SPARE: %d\r\n", Data.bytesPerSpare);
	bufferPrintf("nand: BYTES_PER_PAGE: %d\r\n", Data.bytesPerPage);
	bufferPrintf("nand: PAGES_PER_BLOCK: %d\r\n", Data.pagesPerBlock);

	aTemporaryReadEccBuf = (uint8_t*) malloc(Data.bytesPerPage);
	memset(aTemporaryReadEccBuf, 0xFF, SECTOR_SIZE);

	aTemporarySBuf = (uint8_t*) malloc(Data.bytesPerSpare);

	HasNANDInit = TRUE;

	return 0;
}
Пример #4
0
int nand_setup() {
	if(HasNANDInit)
		return 0;

	WEHighHoldTime = 7;
	WPPulseTime = 7;
	NANDSetting3 = 7;
	NANDSetting4 = 7;

	bufferPrintf("nand: Probing flash controller...\r\n");

	clock_gate_switch(NAND_CLOCK_GATE1, ON);
	clock_gate_switch(NAND_CLOCK_GATE2, ON);

	int bank;
	for(bank = 0; bank < NAND_NUM_BANKS; bank++) {
		banksTable[bank] = bank;
	}

	NumValidBanks = 0;
	const NANDDeviceType* nandType = NULL;

	SET_REG(NAND + RSCTRL, 0);
	SET_REG(NAND + RSCTRL, GET_REG(NAND + RSCTRL) | (ECCType << 4));

	for(bank = 0; bank < NAND_NUM_BANKS; bank++) {
		nand_bank_reset(bank, 100);

		SET_REG(NAND + FMCTRL1, FMCTRL1_FLUSHFIFOS);
		SET_REG(NAND + FMCTRL0,
			((WEHighHoldTime & FMCTRL_TWH_MASK) << FMCTRL_TWH_SHIFT) | ((WPPulseTime & FMCTRL_TWP_MASK) << FMCTRL_TWP_SHIFT)
			| (1 << (banksTable[bank] + 1)) | FMCTRL0_ON | FMCTRL0_WPB);

		SET_REG(NAND + NAND_CMD, NAND_CMD_ID);

		wait_for_ready(500);

		SET_REG(NAND + FMANUM, 0);
		SET_REG(NAND + FMADDR0, 0);
		SET_REG(NAND + FMCTRL1, FMCTRL1_DOTRANSADDR);

		wait_for_address_done(500);
		wait_for_command_done(bank, 100);

		SET_REG(NAND + FMDNUM, 8);
		SET_REG(NAND + FMCTRL1, FMCTRL1_DOREADDATA);

		wait_for_transfer_done(500);
		uint32_t id = GET_REG(NAND + FMFIFO);
		const NANDDeviceType* candidate = SupportedDevices;
		while(candidate->id != 0) {
			if(candidate->id == id) {
				if(nandType == NULL) {
					nandType = candidate;
				} else if(nandType != candidate) {
					bufferPrintf("nand: Mismatched device IDs (0x%08x after 0x%08x)\r\n", id, nandType->id);
					return ERROR_ARG;
				}
				banksTable[NumValidBanks++] = bank;
			}
			candidate++;
		}

		SET_REG(NAND + FMCTRL1, FMCTRL1_FLUSHFIFOS);
	}

	if(nandType == NULL) {
		bufferPrintf("nand: No supported NAND found\r\n");
		return ERROR_ARG;
	}

	Geometry.DeviceID = nandType->id;
	Geometry.banksTable = banksTable;

	WPPulseTime = (((clock_get_frequency(FrequencyBaseBus) * (nandType->WPPulseTime + 1)) + 99999999)/100000000) - 1;
	WEHighHoldTime = (((clock_get_frequency(FrequencyBaseBus) * (nandType->WEHighHoldTime + 1)) + 99999999)/100000000) - 1;
	NANDSetting3 = (((clock_get_frequency(FrequencyBaseBus) * (nandType->NANDSetting3 + 1)) + 99999999)/100000000) - 1;
	NANDSetting4 = (((clock_get_frequency(FrequencyBaseBus) * (nandType->NANDSetting4 + 1)) + 99999999)/100000000) - 1;

	if(WPPulseTime > 7)
		WPPulseTime = 7;

	if(WEHighHoldTime > 7)
		WEHighHoldTime = 7;

	if(NANDSetting3 > 7)
		NANDSetting3 = 7;

	if(NANDSetting4 > 7)
		NANDSetting4 = 7;

	Geometry.blocksPerBank = nandType->blocksPerBank;
	Geometry.banksTotal = NumValidBanks;
	Geometry.sectorsPerPage = nandType->sectorsPerPage;
	Geometry.userSuBlksTotal = nandType->userSuBlksTotal;
	Geometry.bytesPerSpare = nandType->bytesPerSpare;
	Geometry.field_2E = 4;
	Geometry.field_2F = 3;
	Geometry.pagesPerBlock = nandType->pagesPerBlock;

	if(Geometry.sectorsPerPage > 4) {
		LargePages = TRUE;
	} else {
		LargePages = FALSE;
	}

	if(nandType->ecc1 == 6) {
		ECCType = 4;
		TotalECCDataSize = Geometry.sectorsPerPage * 15;
	} else if(nandType->ecc1 == 8) {
		ECCType = 8;
		TotalECCDataSize = Geometry.sectorsPerPage * 20;
	} else if(nandType->ecc1 == 4) {
		ECCType = 0;
		TotalECCDataSize = Geometry.sectorsPerPage * 10;
	}

	if(nandType->ecc2 == 6) {
		ECCType2 = 4;
	} else if(nandType->ecc2 == 8) {
		ECCType2 = 8;
	} else if(nandType->ecc2 == 4) {
		ECCType2 = 0;
	}

	Geometry.field_4 = 5;
	Geometry.bytesPerPage = SECTOR_SIZE * Geometry.sectorsPerPage;
	Geometry.pagesPerBank = Geometry.pagesPerBlock * Geometry.blocksPerBank;
	Geometry.pagesTotal = Geometry.pagesPerBank * Geometry.banksTotal;
	Geometry.pagesPerSuBlk = Geometry.pagesPerBlock * Geometry.banksTotal;
	Geometry.userPagesTotal = Geometry.userSuBlksTotal * Geometry.pagesPerSuBlk;
	Geometry.suBlksTotal = (Geometry.banksTotal * Geometry.blocksPerBank) / Geometry.banksTotal;

	FTLData.field_2 = Geometry.suBlksTotal - Geometry.userSuBlksTotal - 28;
	FTLData.sysSuBlks = FTLData.field_2 + 4;
	FTLData.field_4 = FTLData.field_2 + 5;
	FTLData.field_6 = 3;
	FTLData.field_8 = 23;
	if(FTLData.field_8 == 0)
		Geometry.field_22 = 0;

	int bits = 0;
	int i = FTLData.field_8;
	while((i <<= 1) != 0) {
		bits++;
	}

	Geometry.field_22 = bits;

	bufferPrintf("nand: DEVICE: %08x\r\n", Geometry.DeviceID);
	bufferPrintf("nand: BANKS_TOTAL: %d\r\n", Geometry.banksTotal);
	bufferPrintf("nand: BLOCKS_PER_BANK: %d\r\n", Geometry.blocksPerBank);
	bufferPrintf("nand: SUBLKS_TOTAL: %d\r\n", Geometry.suBlksTotal);
	bufferPrintf("nand: USER_SUBLKS_TOTAL: %d\r\n", Geometry.userSuBlksTotal);
	bufferPrintf("nand: PAGES_PER_SUBLK: %d\r\n", Geometry.pagesPerSuBlk);
	bufferPrintf("nand: PAGES_PER_BANK: %d\r\n", Geometry.pagesPerBank);
	bufferPrintf("nand: SECTORS_PER_PAGE: %d\r\n", Geometry.sectorsPerPage);
	bufferPrintf("nand: BYTES_PER_SPARE: %d\r\n", Geometry.bytesPerSpare);
	bufferPrintf("nand: BYTES_PER_PAGE: %d\r\n", Geometry.bytesPerPage);
	bufferPrintf("nand: PAGES_PER_BLOCK: %d\r\n", Geometry.pagesPerBlock);

	aTemporaryReadEccBuf = (uint8_t*) malloc(Geometry.bytesPerPage);
	memset(aTemporaryReadEccBuf, 0xFF, SECTOR_SIZE);

	aTemporarySBuf = (uint8_t*) malloc(Geometry.bytesPerSpare);

	HasNANDInit = TRUE;

	return 0;
}