lib/sw_apps/zynq_fsbl/src/nand.c
u32 NandAccess(u32 SourceAddress, u32 DestinationAddress, u32 LengthBytes)
{
	u32 ActLen;
	u32 BlockOffset;
	u32 Block;
	u32 Status;
	u32 BytesLeft = LengthBytes;
	u32 BlockSize = NandInstPtr->Geometry.BlockSize;
	u8 *BufPtr = (u8 *)DestinationAddress;
	u32 ReadLen;
	u32 BlockReadLen;
	u32 Offset;
	u32 TmpAddress = 0 ;
	u32 BlockCount = 0;
	u32 BadBlocks = 0;

	/*
	 * First get bad blocks before the source address
	 */
	while (TmpAddress < SourceAddress) {
		while (XNandPs_IsBlockBad(NandInstPtr, BlockCount) ==
				XST_SUCCESS) {
			BlockCount ++;
			BadBlocks ++;
		}

		TmpAddress += BlockSize;
		BlockCount ++;
	}

	Offset = SourceAddress + BadBlocks * BlockSize;

	/*
	 * Calculate the actual length including bad blocks
	 */
	ActLen = XNandPs_CalculateLength(NandInstPtr, Offset, LengthBytes);

	/*
	 *  Check if the actual length cross flash size
	 */
	if (Offset + ActLen > NandInstPtr->Geometry.DeviceSize) {
		return XST_FAILURE;
	}

	while (BytesLeft > 0) {
		BlockOffset = Offset & (BlockSize - 1);
		Block = (Offset & ~(BlockSize - 1))/BlockSize;
		BlockReadLen = BlockSize - BlockOffset;

		Status = XNandPs_IsBlockBad(NandInstPtr, Block);
		if (Status == XST_SUCCESS) {
			/* Move to next block */
			Offset += BlockReadLen;
			continue;
		}

		/*
		 * Check if we cross block boundary
		 */
		if (BytesLeft < BlockReadLen) {
			ReadLen = BytesLeft;
		} else {
			ReadLen = BlockReadLen;
		}

		/*
		 * Read from the NAND flash
		 */
		Status = XNandPs_Read(NandInstPtr, Offset, ReadLen, BufPtr, NULL);
		if (Status != XST_SUCCESS) {
			return Status;
		}
		BytesLeft -= ReadLen;
		Offset += ReadLen;
		BufPtr += ReadLen;
	}

	return XST_SUCCESS;
}
/******************************************************************************/
/**
*
* This function provides the NAND FLASH interface for the Simplified header
* functionality. This function handles bad blocks.
*
* The source address is the absolute good address, bad blocks are skipped
* without incrementing the source address.
*
* @param	SourceAddress is address in FLASH data space, absolute good address
* @param	DestinationAddress is address in OCM data space
*
* @return	XST_SUCCESS if the transfer completes correctly
*		XST_FAILURE if the transfer fails to completes correctly
*
* @note	none.
*
****************************************************************************/
This function provides the NAND FLASH interface for the Simplified header
functionality. This function handles bad blocks.

The source address is the absolute good address, bad blocks are skipped
without incrementing the source address.
This function provides the NAND FLASH interface for the Simplified header functionality . This function handles bad blocks . The source address is the absolute good address bad blocks are skipped without incrementing the source address .
u32 NandAccess(u32 SourceAddress, u32 DestinationAddress, u32 LengthBytes)
{
	u32 ActLen;
	u32 BlockOffset;
	u32 Block;
	u32 Status;
	u32 BytesLeft = LengthBytes;
	u32 BlockSize = NandInstPtr->Geometry.BlockSize;
	u8 *BufPtr = (u8 *)DestinationAddress;
	u32 ReadLen;
	u32 BlockReadLen;
	u32 Offset;
	u32 TmpAddress = 0 ;
	u32 BlockCount = 0;
	u32 BadBlocks = 0;
	while (TmpAddress < SourceAddress) {
		while (XNandPs_IsBlockBad(NandInstPtr, BlockCount) ==
				XST_SUCCESS) {
			BlockCount ++;
			BadBlocks ++;
		}
		TmpAddress += BlockSize;
		BlockCount ++;
	}
	Offset = SourceAddress + BadBlocks * BlockSize;
	ActLen = XNandPs_CalculateLength(NandInstPtr, Offset, LengthBytes);
	if (Offset + ActLen > NandInstPtr->Geometry.DeviceSize) {
		return XST_FAILURE;
	}
	while (BytesLeft > 0) {
		BlockOffset = Offset & (BlockSize - 1);
		Block = (Offset & ~(BlockSize - 1))/BlockSize;
		BlockReadLen = BlockSize - BlockOffset;
		Status = XNandPs_IsBlockBad(NandInstPtr, Block);
		if (Status == XST_SUCCESS) {
			Offset += BlockReadLen;
			continue;
		}
		if (BytesLeft < BlockReadLen) {
			ReadLen = BytesLeft;
		} else {
			ReadLen = BlockReadLen;
		}
		Status = XNandPs_Read(NandInstPtr, Offset, ReadLen, BufPtr, NULL);
		if (Status != XST_SUCCESS) {
			return Status;
		}
		BytesLeft -= ReadLen;
		Offset += ReadLen;
		BufPtr += ReadLen;
	}
	return XST_SUCCESS;
}
u32 NandAccess ( u32 SourceAddress , u32 DestinationAddress , u32 LengthBytes ) { u32 ActLen ; u32 BlockOffset ; u32 Block ; u32 Status ; u32 BytesLeft = LengthBytes ; u32 BlockSize = NandInstPtr -> Geometry . BlockSize ; u8 * BufPtr = ( u8 * ) DestinationAddress ; u32 ReadLen ; u32 BlockReadLen ; u32 Offset ; u32 TmpAddress = 0 ; u32 BlockCount = 0 ; u32 BadBlocks = 0 ; while ( TmpAddress < SourceAddress ) { while ( XNandPs_IsBlockBad ( NandInstPtr , BlockCount ) == XST_SUCCESS ) { BlockCount ++ ; BadBlocks ++ ; } TmpAddress += BlockSize ; BlockCount ++ ; } Offset = SourceAddress + BadBlocks * BlockSize ; ActLen = XNandPs_CalculateLength ( NandInstPtr , Offset , LengthBytes ) ; if ( Offset + ActLen > NandInstPtr -> Geometry . DeviceSize ) { return XST_FAILURE ; } while ( BytesLeft > 0 ) { BlockOffset = Offset & ( BlockSize - 1 ) ; Block = ( Offset & ~ ( BlockSize - 1 ) ) / BlockSize ; BlockReadLen = BlockSize - BlockOffset ; Status = XNandPs_IsBlockBad ( NandInstPtr , Block ) ; if ( Status == XST_SUCCESS ) { Offset += BlockReadLen ; continue ; } if ( BytesLeft < BlockReadLen ) { ReadLen = BytesLeft ; } else { ReadLen = BlockReadLen ; } Status = XNandPs_Read ( NandInstPtr , Offset , ReadLen , BufPtr , NULL ) ; if ( Status != XST_SUCCESS ) { return Status ; } BytesLeft -= ReadLen ; Offset += ReadLen ; BufPtr += ReadLen ; } return XST_SUCCESS ; }
This function provides the NAND FLASH interface for the Simplified header
functionality.
This function provides the NAND FLASH interface for the Simplified header functionality .
/*
	 * First get bad blocks before the source address
	 */ /*
	 * Calculate the actual length including bad blocks
	 */ /*
	 *  Check if the actual length cross flash size
	 */ /* Move to next block */ /*
		 * Check if we cross block boundary
		 */ /*
		 * Read from the NAND flash
		 */