Пример #1
0
/**
*
* Read a CompactFlash sector. This is a blocking, low-level function which
* does not return until the specified sector is read.
*
* @param BaseAddress is the base address of the device
* @param SectorId is the id of the sector to read
* @param BufferPtr is a pointer to a buffer where the data will be stored.
*
* @return
*
* The number of bytes read. If this number is not equal to the sector size,
* 512 bytes, then an error occurred.
*
* @note
*
* None.
*
******************************************************************************/
int XSysAce_ReadSector(Xuint32 BaseAddress, Xuint32 SectorId, Xuint8 *BufferPtr)
{
    int NumRead;

    /* Request and wait for the lock */
    XSysAce_mWaitForLock(BaseAddress);

    /* See if the CF is ready for a command */
    if (!XSysAce_mIsReadyForCmd(BaseAddress))
    {
        return 0;
    }

    /* Write the sector ID (LBA) */
    XSysAce_RegWrite32(BaseAddress + XSA_MLR_OFFSET, SectorId);

    /* Send a read command of one sector to the controller */
    XSysAce_RegWrite16(BaseAddress + XSA_SCCR_OFFSET,
                        XSA_SCCR_READDATA_MASK | 1);

    /* Reset configuration controller (be sure to keep the lock) */
    XSysAce_mOrControlReg(BaseAddress, XSA_CR_CFGRESET_MASK);

    /* Read a sector of data from the data buffer */
    NumRead = XSysAce_ReadDataBuffer(BaseAddress, BufferPtr,
                                     XSA_CF_SECTOR_SIZE);

    /* Clear reset of configuration controller and locks */
    XSysAce_mAndControlReg(BaseAddress, ~(XSA_CR_CFGRESET_MASK |
                           XSA_CR_LOCKREQ_MASK));

    return NumRead;
}
Пример #2
0
/**
*
* Handle a data-buffer-ready interrupt. If we get the interrupt when reading,
* it means there is still data to read since the interrupt does not occur after
* reading the last data buffer. If we get the interrupt when writing, there
* may or may not be data left to write since the interrupt does occur after the
* last data buffer is written.
*
* @param InstancePtr is a pointer to the XSysAce instance to be worked on.
* @param StatusReg is the contents of the status register, read at the start
*        of the interrupt service routine.
*
* @return
*
* None.
*
* @note
*
* None.
*
******************************************************************************/
static void HandleDataBuffer(XSysAce * InstancePtr, u32 StatusReg)
{
	/* By default, transfer a whole data buffer */
	int BytesToTransfer = XSA_DATA_BUFFER_SIZE;

	/*
	 * Check to see if number of bytes remaining is less than the data buffer
	 * size. If it is, we need to adjust the remaining bytes to transfer.
	 */
	if (InstancePtr->NumRemaining < XSA_DATA_BUFFER_SIZE) {
		BytesToTransfer = InstancePtr->NumRemaining;
	}

	/*
	 * Transfer only one data buffer at a time, which is 32 bytes. Note that
	 * errors will be handled by an error interrupt occurring, so no need to
	 * check for them here.
	 */
	if (StatusReg & XSA_SR_DATABUFMODE_MASK) {
		/*
		 * A write operation in progress, so if there is data remaining then
		 * write the buffer. If no data is remaining, clean up.
		 */
		if (InstancePtr->NumRemaining > 0) {
			(void) XSysAce_WriteDataBuffer(InstancePtr->BaseAddress,
						       InstancePtr->BufferPtr,
						       BytesToTransfer);

			/*
			 * Decrement the number of bytes remaining to be transferred and
			 * adjust the buffer pointer appropriately.
			 */
			InstancePtr->NumRemaining -= BytesToTransfer;
			InstancePtr->BufferPtr += BytesToTransfer;
		}
		else {
			/* Done writing data, so clean up */
			DataComplete(InstancePtr);
		}
	}
	else {
		/* A read operation in progress, so read the buffer */
		(void) XSysAce_ReadDataBuffer(InstancePtr->BaseAddress,
					      InstancePtr->BufferPtr,
					      BytesToTransfer);

		/*
		 * Decrement the number of bytes remaining to be transferred and
		 * adjust the buffer pointer appropriately. If it was the last buffer,
		 * we're done and we can cleanup.
		 */
		InstancePtr->NumRemaining -= BytesToTransfer;
		InstancePtr->BufferPtr += BytesToTransfer;

		if (InstancePtr->NumRemaining == 0) {
			/* Done reading data, so clean up */
			DataComplete(InstancePtr);
		}
	}
}
Пример #3
0
/**
*
* Read at least one sector of data from the CompactFlash. The user specifies
* the starting sector ID and the number of sectors to be read. The minimum unit
* that can be read from the CompactFlash is a sector, which is 512 bytes.
*
* In polled mode, this read is blocking. If there are other tasks in the system
* that must run, it is best to keep the number of sectors to be read to a
* minimum (e.g., 1). In interrupt mode, this read is non-blocking and an event,
* XSA_EVENT_DATA_DONE, is returned to the user in the asynchronous event
* handler when the read is complete. The user must call
* XSysAce_EnableInterrupt() to put the driver/device into interrupt mode.
*
* An MPU lock, obtained using XSysAce_Lock(), must be granted before calling
* this function. If a lock has not been granted, no action is taken and an
* error is returned.
*
* @param	InstancePtr is a pointer to the XSysAce instance.
* @param	StartSector is the starting sector ID from where data will
*		be read.
*		Sector IDs range from 0 (first sector) to 0x10000000.
* @param	NumSectors is the number of sectors to read.
*		The range can be from 1 to 256.
* @param	BufferPtr is a pointer to a buffer where the data will be
*		stored. The user must ensure it is big enough to hold
*		(512 * NumSectors) bytes.
*
* @return
*		- XST_SUCCESS if the read was successful. In interrupt mode,
*		this does not mean the read is complete, only that it has begun.
*		An event is returned to the user when the read is complete.
*		- XST_SYSACE_NO_LOCK if no MPU lock has yet been granted
*		- XST_DEVICE_BUSY if the ACE controller is not ready for a
*		command
*		- XST_FAILURE if an error occurred during the read. The user
*		should call XSysAce_GetErrors() to determine the cause of the
*		error.
*
* @note		None.
*
* @internal
*
* Polled mode is blocking under the assumption that a single sector can be
* transferred at a very fast rate (>20 Mbps).  So, the user can choose to
* transfer only single sectors when in polled mode, thus allowing time for
* other work to be done. The biggest issue is that although data transfer
* rates are high, seek time for CompactFlash cards is slow (5-20 ms on
* average, depending on the type of device). We could move to a non-blocking
* solution that transfers 32 bytes at a time (the entire data buffer) and
* then returns. The user would then need to increment its buffer pointer
* appropriately and call the read/write again. The driver would need some way
* to know not to issue a new command to the CompactFlash, but instead continue
* with the previous command.  This can be done either with a NumSectors argument
* of zero to indicate that there is already an operation in progress, or by
* having the driver keep state to know there is an operation in progress. The
* interface for either seems a bit awkward. Also, the hit for seek time needs
* to be taken regardless of the blocking or non-blocking nature of the call, so
* the additional few microseconds to transfer a sector of data seems acceptable.
*
******************************************************************************/
int XSysAce_SectorRead(XSysAce *InstancePtr, u32 StartSector,
		       int NumSectors, u8 *BufferPtr)
{
	u16 SectorCmd;
	int BytesToRecv;

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(NumSectors > 0 &&
			NumSectors <= (XSA_SCCR_COUNT_MASK + 1));
	Xil_AssertNonvoid(BufferPtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/* If a lock has not been granted, return an error */
	if (!XSysAce_IsMpuLocked(InstancePtr->BaseAddress)) {
		return XST_SYSACE_NO_LOCK;
	}

	/* See if the CF is ready for a command */
	if (!XSysAce_IsReadyForCmd(InstancePtr->BaseAddress)) {
		return XST_DEVICE_BUSY;
	}

	BytesToRecv = XSA_CF_SECTOR_SIZE * NumSectors;

	/*
	 * If in interrupt mode, set up the state variables and enable the
	 * data-buffer-ready interrupt. This needs to be done before the command
	 * is sent to the ACE, which will cause the interrupt to occur.
	 */
	if (XSysAce_IsIntrEnabled(InstancePtr->BaseAddress)) {
		InstancePtr->NumRequested = BytesToRecv;
		InstancePtr->NumRemaining = BytesToRecv;
		InstancePtr->BufferPtr = BufferPtr;

		XSysAce_OrControlReg(InstancePtr->BaseAddress,
				      XSA_CR_DATARDYIRQ_MASK);
	}

	/* Write the sector ID (LBA) */
	XSysAce_RegWrite32(InstancePtr->BaseAddress + XSA_MLR_OFFSET,
			   StartSector);

	/*
	 * Send the read command for the number of sectors specified
	 */
	SectorCmd = (NumSectors & XSA_SCCR_COUNT_MASK) | XSA_SCCR_READDATA_MASK;
	XSysAce_RegWrite16(InstancePtr->BaseAddress + XSA_SCCR_OFFSET,
			   SectorCmd);

	/*
	 * If in polled mode, receive the entire amount requested
	 */
	if (!XSysAce_IsIntrEnabled(InstancePtr->BaseAddress)) {
		int NumRead;

		/* Reset configuration controller (be sure to keep the lock) */
		/* This breaks mvl, beware! */
		/*XSysAce_OrControlReg(InstancePtr->BaseAddress, XSA_CR_CFGRESET_MASK); */

		NumRead = XSysAce_ReadDataBuffer(InstancePtr->BaseAddress,
					       BufferPtr, BytesToRecv);
		/* Clear reset of configuration controller */
		/* This breaks mvl, beware! */
		/*XSysAce_AndControlReg(InstancePtr->BaseAddress, ~(XSA_CR_CFGRESET_MASK)); */

		if (NumRead != BytesToRecv) {
			/* an error occurred, report this to the user */
			return XST_FAILURE;
		}
	}

	return XST_SUCCESS;
}
Пример #4
0
/**
*
* Identify the CompactFlash device. Retrieves the parameters for the
* CompactFlash storage device. Note that this is a polled read of one sector
* of data. The data is read from the CompactFlash into a byte buffer, which
* is then copied into the XSysAce_CFParameters structure passed in by the
* user.  The copy is necessary since we don't know how the compiler packs
* the XSysAce_CFParameters structure.
*
* An MPU lock, obtained using XSysAce_Lock(), must be granted before calling
* this function. If a lock has not been granted, no action is taken and an
* error is returned.
*
* @param	InstancePtr is a pointer to the XSysAce instance .
* @param	ParamPtr is a pointer to a XSysAce_CFParameters structure where
*		the information for the CompactFlash device will be stored. See
*		xsysace.h for details on the XSysAce_CFParameters structure.
*
* @return
*		- XST_SUCCESS if the identify was done successfully
*		- XST_FAILURE if an error occurs. Use XSysAce_GetErrors() to
*		determine cause.
*		- XST_SYSACE_NO_LOCK if no MPU lock has yet been granted
*		- XST_DEVICE_BUSY if the CompactFlash is not ready for a command
*
* @note		None.
*
* @internal
*
* The identify command has the same protocol as the read sector command
* according to the CompactFlash specification.  However, there is a discepency
* in that same specification on the size of the parameter structure. The word
* addresses defined in the spec indicate the parameter information is a full
* 512 bytes, the same size as a sector. The total bytes defined in the spec,
* however, indicate that the parameter information is only 500 bytes. We
* defined the parameter structure in xsysace.h assuming the parameters are the
* full 512 bytes since that makes sense, and therefore ignored the "Total
* Bytes" column in the spec.
*
* The SectorData variable was made static to avoid putting 512 bytes on the
* stack every time this function is called.
*
******************************************************************************/
int XSysAce_IdentifyCF(XSysAce *InstancePtr, XSysAce_CFParameters * ParamPtr)
{
	int NumRead;
	u32 InterruptsOn;
	static u8 SectorData[XSA_CF_SECTOR_SIZE];

	Xil_AssertNonvoid(InstancePtr != NULL);
	Xil_AssertNonvoid(ParamPtr != NULL);
	Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/* If a lock has not been granted, return an error */
	if (!XSysAce_IsMpuLocked(InstancePtr->BaseAddress)) {
		return XST_SYSACE_NO_LOCK;
	}

	/* See if the CF is ready for a command */
	if (!XSysAce_IsReadyForCmd(InstancePtr->BaseAddress)) {
		return XST_DEVICE_BUSY;
	}

	/*
	 * If interrupts are enabled, we disable them because we want to do this
	 * identify in polled mode - due to the buffer endian conversion and copy
	 * that takes place.
	 */
	InterruptsOn = XSysAce_IsIntrEnabled(InstancePtr->BaseAddress);
	if (InterruptsOn) {
		XSysAce_DisableInterrupt(InstancePtr);
	}

	/*
	 * Send the identify command
	 */
	XSysAce_RegWrite16(InstancePtr->BaseAddress + XSA_SCCR_OFFSET,
			   XSA_SCCR_IDENTIFY_MASK);

	/* Reset configuration controller (be sure to keep the lock) */
	/* This breaks mvl, beware! */
	/* XSysAce_OrControlReg(InstancePtr->BaseAddress, XSA_CR_CFGRESET_MASK); */

	/*
	 * Read a sector of data from the data buffer. The parameter info is
	 * the same size as a sector.
	 */
	NumRead = XSysAce_ReadDataBuffer(InstancePtr->BaseAddress, SectorData,
					 XSA_CF_SECTOR_SIZE);

	/* Clear reset of configuration controller */
	/* This breaks mvl, beware! */
	/*XSysAce_AndControlReg(InstancePtr->BaseAddress, ~(XSA_CR_CFGRESET_MASK)); */

	/* If interrupts were on, re-enable interrupts (regardless of error) */
	if (InterruptsOn) {
		XSysAce_EnableInterrupt(InstancePtr);
	}

	if (NumRead == 0) {
		/* an error occurred */
		return XST_FAILURE;
	}

	/*
	 * Copy the byte buffer to the parameter structure
	 */
	FillParam(ParamPtr, SectorData);

	return XST_SUCCESS;
}