コード例 #1
0
ファイル: ff_file.c プロジェクト: BigEd/pyldin
static FF_ERROR FF_ReadClusters(FF_FILE *pFile, FF_T_UINT32 Count, FF_T_UINT8 *buffer) {
	FF_T_UINT32 ulSectors;
	FF_T_UINT32 SequentialClusters = 0;
	FF_T_UINT32 nItemLBA;
	FF_T_SINT32 slRetVal;
	FF_ERROR	Error;

	while(Count != 0) {
		if((Count - 1) > 0) {
			SequentialClusters = FF_GetSequentialClusters(pFile->pIoman, pFile->AddrCurrentCluster, (Count - 1), &Error);
			if(Error) {
				return Error;
			}
		}
		ulSectors = (SequentialClusters + 1) * pFile->pIoman->pPartition->SectorsPerCluster;
		nItemLBA = FF_Cluster2LBA(pFile->pIoman, pFile->AddrCurrentCluster);
		nItemLBA = FF_getRealLBA(pFile->pIoman, nItemLBA);

		slRetVal = FF_BlockRead(pFile->pIoman, nItemLBA, ulSectors, buffer);
		if(slRetVal < 0) {
			return slRetVal;
		}
		
		Count -= (SequentialClusters + 1);
		pFile->AddrCurrentCluster = FF_TraverseFAT(pFile->pIoman, pFile->AddrCurrentCluster, (SequentialClusters + 1), &Error);
		if(Error) {
			return Error;
		}
		pFile->CurrentCluster += (SequentialClusters + 1);
		buffer += ulSectors * pFile->pIoman->BlkSize;
		SequentialClusters = 0;
	}

	return FF_ERR_NONE;
}
コード例 #2
0
ファイル: ff_ioman.c プロジェクト: BigEd/pyldin
FF_BUFFER *FF_GetBuffer(FF_IOMAN *pIoman, FF_T_UINT32 Sector, FF_T_UINT8 Mode) {
	FF_BUFFER	*pBuffer;
	FF_BUFFER	*pBufLRU	= NULL;
	FF_BUFFER	*pBufLHITS	= NULL;
	FF_BUFFER	*pBufMatch	= NULL;

	FF_T_UINT32	i;

	while(!pBufMatch) {
		FF_PendSemaphore(pIoman->pSemaphore);
		{
			pBuffer = pIoman->pBuffers;
			// HT if a perfect match has priority, find that first
			for(i = 0; i < pIoman->CacheSize; i++, pBuffer++) {
				pBuffer = (pIoman->pBuffers + i);
				if(pBuffer->Sector == Sector && pBuffer->Valid == FF_TRUE) {
					pBufMatch = pBuffer;
					break;	// Why look further if you found a perfect match?
				}
			}

			if(pBufMatch) {
				// A Match was found process!
				if(Mode == FF_MODE_READ && pBufMatch->Mode == FF_MODE_READ) {
					pBufMatch->NumHandles += 1;
					pBufMatch->Persistance += 1;
					FF_ReleaseSemaphore(pIoman->pSemaphore);
					return pBufMatch;
				}

				if(pBufMatch->Mode == FF_MODE_WRITE && pBufMatch->NumHandles == 0) {	// This buffer has no attached handles.
					pBufMatch->Mode = Mode;
					pBufMatch->NumHandles = 1;
					pBufMatch->Persistance += 1;
					FF_ReleaseSemaphore(pIoman->pSemaphore);
					return pBufMatch;
				}

				if(pBufMatch->Mode == FF_MODE_READ && Mode == FF_MODE_WRITE && pBufMatch->NumHandles == 0) {
					pBufMatch->Mode = Mode;
					pBufMatch->Modified = FF_TRUE;
					pBufMatch->NumHandles = 1;
					pBufMatch->Persistance += 1;
					FF_ReleaseSemaphore(pIoman->pSemaphore);
					return pBufMatch;
				}

				pBufMatch = NULL;	// Sector is already in use, keep yielding until its available!

			} else {
				pBuffer = pIoman->pBuffers;
				for(i = 0; i < pIoman->CacheSize; i++, pBuffer++) {
					if(pBuffer->NumHandles == 0) {
						pBuffer->LRU += 1;

						if(!pBufLRU) {
							pBufLRU = pBuffer;
						}
						if(!pBufLHITS) {
							pBufLHITS = pBuffer;
						}

						if(pBuffer->LRU >= pBufLRU->LRU) {
							if(pBuffer->LRU == pBufLRU->LRU) {
								if(pBuffer->Persistance > pBufLRU->Persistance) {
									pBufLRU = pBuffer;
								}
							} else {
								pBufLRU = pBuffer;
							}
						}

						if(pBuffer->Persistance < pBufLHITS->Persistance) {
							pBufLHITS = pBuffer;
						}
					}
				}

				if(pBufLRU) {
					// Process the suitable candidate.
					if(pBufLRU->Modified == FF_TRUE) {
						FF_BlockWrite(pIoman, pBufLRU->Sector, 1, pBufLRU->pBuffer);
					}
					pBufLRU->Mode = Mode;
					pBufLRU->Persistance = 1;
					pBufLRU->LRU = 0;
					pBufLRU->NumHandles = 1;
					pBufLRU->Sector = Sector;

					if(Mode == FF_MODE_WRITE) {
						pBufLRU->Modified = FF_TRUE;
					} else {
						pBufLRU->Modified = FF_FALSE;
					}

					FF_BlockRead(pIoman, Sector, 1, pBufLRU->pBuffer);
					pBufLRU->Valid = FF_TRUE;
					FF_ReleaseSemaphore(pIoman->pSemaphore);
					return pBufLRU;
				}

			}
		}
		FF_ReleaseSemaphore(pIoman->pSemaphore);
		FF_Yield();	// Better to go asleep to give low-priority task a chance to release buffer(s)
	}

	return pBufMatch;	// Return the Matched Buffer!
}
コード例 #3
0
ファイル: ff_ioman.c プロジェクト: jgottula/automaton
FF_BUFFER *FF_GetBuffer(FF_IOMAN *pIoman, FF_T_UINT32 Sector, FF_T_UINT8 Mode) {
	FF_BUFFER	*pBuffer;
	FF_BUFFER	*pBufLRU;
//	FF_BUFFER	*pBufLHITS = NULL;  // Wasn't use anymore?
	FF_BUFFER	*pBufMatch = NULL;
	FF_T_SINT32	RetVal;
	FF_T_INT    LoopCount = FF_GETBUFFER_WAIT_TIME;

	FF_T_INT cacheSize = pIoman->CacheSize;
	if (cacheSize <= 0) {
		return NULL;
	}

	while(!pBufMatch) {
		if (!--LoopCount) {
			//
			// *pError = FF_ERR_IOMAN_GETBUFFER_TIMEOUT;
			//
			return NULL;
		}
		FF_PendSemaphore(pIoman->pSemaphore);
		{

			for(pBuffer = pIoman->pBuffers; pBuffer < pIoman->pBuffers + cacheSize; pBuffer++) {
				if(pBuffer->Sector == Sector && pBuffer->Valid) {
					pBufMatch = pBuffer;
					break;	// Don't look further if you found a perfect match
				}
			}

			if(pBufMatch) {
				// A Match was found process!
				if(Mode == FF_MODE_READ && pBufMatch->Mode == FF_MODE_READ) {
					pBufMatch->NumHandles += 1;
					pBufMatch->Persistance += 1;
					break;
				}

				if(pBufMatch->NumHandles == 0) {
					pBufMatch->Mode = (Mode & FF_MODE_RD_WR);
					if((Mode & FF_MODE_WRITE) != 0) {	// This buffer has no attached handles.
						pBufMatch->Modified = FF_TRUE;
					}
					pBufMatch->NumHandles = 1;
					pBufMatch->Persistance += 1;
					break;
				}

				pBufMatch = NULL;	// Sector is already in use, keep yielding until its available!

			} else {
				pBufLRU   = NULL;	// So put them to NULL here

				for(pBuffer = pIoman->pBuffers; pBuffer < pIoman->pBuffers + cacheSize; pBuffer++) {
					if(pBuffer->NumHandles)
						continue;  // Occupied
					pBuffer->LRU += 1;

					if(!pBufLRU) {
						pBufLRU = pBuffer;
					}

					if(pBuffer->LRU > pBufLRU->LRU ||
					   (pBuffer->LRU == pBufLRU->LRU && pBuffer->Persistance > pBufLRU->Persistance)) {
						pBufLRU = pBuffer;
					}

				}
				// Choose a suitable buffer!
				if(pBufLRU) {
					// Process the suitable candidate.
					if(pBufLRU->Modified == FF_TRUE) {
						// Along with the FF_TRUE parameter to indicate semapahore has been claimed

						RetVal = FF_BlockWrite(pIoman, pBufLRU->Sector, 1, pBufLRU->pBuffer, FF_TRUE);
						if (RetVal < 0) {
							pBufMatch = NULL;
							break;
						}
					}
					if (Mode == FF_MODE_WR_ONLY) {
						memset (pBufLRU->pBuffer, '\0', pIoman->BlkSize);
					} else {
						RetVal = FF_BlockRead(pIoman, Sector, 1, pBufLRU->pBuffer, FF_TRUE);
						if (RetVal < 0) {
							pBufMatch = NULL;
							break;
						}
					}
					pBufLRU->Mode = (Mode & FF_MODE_RD_WR);
					pBufLRU->Persistance = 1;
					pBufLRU->LRU = 0;
					pBufLRU->NumHandles = 1;
					pBufLRU->Sector = Sector;

					pBufLRU->Modified = (Mode & FF_MODE_WRITE) != 0;

					pBufLRU->Valid = FF_TRUE;
					pBufMatch = pBufLRU;
					break;
				}

			}
		}
		FF_ReleaseSemaphore(pIoman->pSemaphore);
		// Better to go asleep to give low-priority task a chance to release buffer(s)
		FF_Sleep (FF_GETBUFFER_SLEEP_TIME);
	}	// while(!pBufMatch)
	FF_ReleaseSemaphore(pIoman->pSemaphore);

	return pBufMatch;	// Return the Matched Buffer!
}
コード例 #4
0
ファイル: ff_file.c プロジェクト: BigEd/pyldin
/**
 *	@public
 *	@brief	Equivalent to fread()
 *
 *	@param	pFile		FF_FILE object that was created by FF_Open().
 *	@param	ElementSize	The size of an element to read.
 *	@param	Count		The number of elements to read.
 *	@param	buffer		A pointer to a buffer of adequate size to be filled with the requested data.
 *
 *	@return Number of bytes read.
 *
 **/
FF_T_SINT32 FF_Read(FF_FILE *pFile, FF_T_UINT32 ElementSize, FF_T_UINT32 Count, FF_T_UINT8 *buffer) {
	FF_T_UINT32 nBytes = ElementSize * Count;
	FF_T_UINT32	nBytesRead = 0;
	FF_T_UINT32 nBytesToRead;
	FF_IOMAN	*pIoman;
	FF_BUFFER	*pBuffer;
	FF_T_UINT32 nRelBlockPos;
	FF_T_UINT32	nItemLBA;
	FF_T_SINT32	RetVal = 0;
	FF_T_UINT16	sSectors;
	FF_T_UINT32 nRelClusterPos;
	FF_T_UINT32 nBytesPerCluster;
	FF_T_UINT32	nClusterDiff;
	FF_ERROR	Error;

	if(!pFile) {
		return FF_ERR_NULL_POINTER;
	}

	if(!(pFile->Mode & FF_MODE_READ)) {
		return FF_ERR_FILE_NOT_OPENED_IN_READ_MODE;
	}

	pIoman = pFile->pIoman;

	if(pFile->FilePointer == pFile->Filesize) {
		return 0;
	}

	if((pFile->FilePointer + nBytes) > pFile->Filesize) {
		nBytes = pFile->Filesize - pFile->FilePointer;
	}
	
	nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster;
	if(nClusterDiff) {
		if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) {
			pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff, &Error);
			if(Error) {
				return Error;
			}
			pFile->CurrentCluster += nClusterDiff;
		}
	}

	nRelBlockPos = FF_getMinorBlockEntry(pIoman, pFile->FilePointer, 1); // Get the position within a block.
	
	nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster);
	nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1);

	if((nRelBlockPos + nBytes) < pIoman->BlkSize) {	// Bytes to read are within a block and less than a block size.
		pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_READ);
		{
			if(!pBuffer) {
				return FF_ERR_DEVICE_DRIVER_FAILED;
			}
			memcpy(buffer, (pBuffer->pBuffer + nRelBlockPos), nBytes);
		}
		FF_ReleaseBuffer(pIoman, pBuffer);

		pFile->FilePointer += nBytes;
		
		return nBytes;		// Return the number of bytes read.

	} else {

		//---------- Read (memcpy) to a Sector Boundary
		if(nRelBlockPos != 0) {	// Not on a sector boundary, at this point the LBA is known.
			nBytesToRead = pIoman->BlkSize - nRelBlockPos;
			pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_READ);
			{
				if(!pBuffer) {
					return FF_ERR_DEVICE_DRIVER_FAILED;
				}
				// Here we copy to the sector boudary.
				memcpy(buffer, (pBuffer->pBuffer + nRelBlockPos), nBytesToRead);
			}
			FF_ReleaseBuffer(pIoman, pBuffer);

			nBytes				-= nBytesToRead;
			nBytesRead			+= nBytesToRead;
			pFile->FilePointer	+= nBytesToRead;
			buffer				+= nBytesToRead;
			
		}

		//---------- Read to a Cluster Boundary
		
		nRelClusterPos = FF_getClusterPosition(pIoman, pFile->FilePointer, 1);
		nBytesPerCluster = (pIoman->pPartition->SectorsPerCluster * pIoman->BlkSize);
		if(nRelClusterPos != 0 && nBytes >= nBytesPerCluster) { // Need to get to cluster boundary
			
			nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster;
			if(nClusterDiff) {
				if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) {
					pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff, &Error);
					if(Error) {
						return Error;
					}
					pFile->CurrentCluster += nClusterDiff;
				}
			}
		
			nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster);
			nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1);

			sSectors = (FF_T_UINT16) (pIoman->pPartition->SectorsPerCluster - (nRelClusterPos / pIoman->BlkSize));
			
			RetVal = FF_BlockRead(pIoman, nItemLBA, (FF_T_UINT32) sSectors, buffer);
			
			nBytesToRead		 = sSectors * pIoman->BlkSize;
			nBytes				-= nBytesToRead;
			buffer				+= nBytesToRead;
			nBytesRead			+= nBytesToRead;
			pFile->FilePointer	+= nBytesToRead;

		}

		//---------- Read Clusters
		if(nBytes >= nBytesPerCluster) {
			//----- Thanks to Christopher Clark of DigiPen Institute of Technology in Redmond, US adding this traversal check.
			nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster;
			if(nClusterDiff) {
				if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) {
					pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff, &Error);
					if(Error) {
						return Error;
					}
					pFile->CurrentCluster += nClusterDiff;
				}
			}
			//----- End of Contributor fix.

			RetVal = FF_ReadClusters(pFile, (nBytes / nBytesPerCluster), buffer);
			if(RetVal < 0) {
				return RetVal;
			}
			nBytesToRead = (nBytesPerCluster *  (nBytes / nBytesPerCluster));

			pFile->FilePointer	+= nBytesToRead;

			nBytes			-= nBytesToRead;
			buffer			+= nBytesToRead;
			nBytesRead		+= nBytesToRead;
		}

		//---------- Read Remaining Blocks
		if(nBytes >= pIoman->BlkSize) {
			sSectors = (FF_T_UINT16) (nBytes / pIoman->BlkSize);
			
			nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster;
			if(nClusterDiff) {
				if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) {
					pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff, &Error);
					if(Error) {
						return Error;
					}
					pFile->CurrentCluster += nClusterDiff;
				}
			}
			
			nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster);
			nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1);

			RetVal = FF_BlockRead(pIoman, nItemLBA, (FF_T_UINT32) sSectors, buffer);

			if(RetVal < 0) {
				return RetVal;
			}
			
			nBytesToRead = sSectors * pIoman->BlkSize;
			pFile->FilePointer	+= nBytesToRead;
			nBytes				-= nBytesToRead;
			buffer				+= nBytesToRead;
			nBytesRead			+= nBytesToRead;
		}

		//---------- Read (memcpy) Remaining Bytes
		if(nBytes > 0) {
			
			nClusterDiff = FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1) - pFile->CurrentCluster;
			if(nClusterDiff) {
				if(pFile->CurrentCluster < FF_getClusterChainNumber(pFile->pIoman, pFile->FilePointer, 1)) {
					pFile->AddrCurrentCluster = FF_TraverseFAT(pIoman, pFile->AddrCurrentCluster, nClusterDiff, &Error);
					if(Error) {
						return Error;
					}
					pFile->CurrentCluster += nClusterDiff;
				}
			}
			
			nItemLBA = FF_Cluster2LBA(pIoman, pFile->AddrCurrentCluster);
			nItemLBA = FF_getRealLBA(pIoman, nItemLBA + FF_getMajorBlockNumber(pIoman, pFile->FilePointer, 1)) + FF_getMinorBlockNumber(pIoman, pFile->FilePointer, 1);
			pBuffer = FF_GetBuffer(pIoman, nItemLBA, FF_MODE_READ);
			{
				if(!pBuffer) {
					return FF_ERR_DEVICE_DRIVER_FAILED;
				}
				memcpy(buffer, pBuffer->pBuffer, nBytes);
			}
			FF_ReleaseBuffer(pIoman, pBuffer);

			nBytesToRead = nBytes;
			pFile->FilePointer	+= nBytesToRead;
			nBytes				-= nBytesToRead;
			buffer				+= nBytesToRead;
			nBytesRead			+= nBytesToRead;

		}
	}

	return nBytesRead;
}