/** * * Reset the CompactFlash device. This function does not reset the System ACE * controller. An ATA soft-reset of the CompactFlash is performed. * * 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 to be worked on. * * @return * * - XST_SUCCESS if the reset was done successfully * - 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. * ******************************************************************************/ int XSysAce_ResetCF(XSysAce * InstancePtr) { XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* If a lock has not been granted, return an error */ if (!XSysAce_mIsMpuLocked(InstancePtr->BaseAddress)) { return XST_SYSACE_NO_LOCK; } /* See if the CF is ready for a command */ if (!XSysAce_mIsReadyForCmd(InstancePtr->BaseAddress)) { return XST_DEVICE_BUSY; } /* * If interrupts are enabled, enable the error interrupt. A reset clears * the error status, so we're going to re-enable the interrupt here so any * new errors will be caught. */ if (XSysAce_mIsIntrEnabled(InstancePtr->BaseAddress)) { XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_ERRORIRQ_MASK); } /* * Send the reset command */ XSysAce_RegWrite16(InstancePtr->BaseAddress + XSA_SCCR_OFFSET, XSA_SCCR_RESET_MASK); return XST_SUCCESS; }
/** * * Write a CompactFlash sector. This is a blocking, low-level function which * does not return until the specified sector is written in its entirety. * * @param BaseAddress is the base address of the device * @param SectorId is the id of the sector to write * @param BufferPtr is a pointer to a buffer used to write the sector. * * @return * * The number of bytes written. If this number is not equal to the sector size, * 512 bytes, then an error occurred. * * @note * * None. * ******************************************************************************/ int XSysAce_WriteSector(Xuint32 BaseAddress, Xuint32 SectorId, Xuint8 *BufferPtr) { int NumSent; /* Get 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 write command of one sector to the controller */ XSysAce_RegWrite16(BaseAddress + XSA_SCCR_OFFSET, XSA_SCCR_WRITEDATA_MASK | 1); /* Reset configuration controller (be sure to keep the lock) */ XSysAce_mOrControlReg(BaseAddress, XSA_CR_CFGRESET_MASK); /* Write a sector of data to the data buffer */ NumSent = XSysAce_WriteDataBuffer(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 NumSent; }
/** * * Initialize a specific XSysAce instance. The configuration information for * the given device ID is found and the driver instance data is initialized * appropriately. * * @param InstancePtr is a pointer to the XSysAce instance to be worked on. * @param DeviceId is the unique id of the device controlled by this XSysAce * instance. * * @return * * XST_SUCCESS if successful, or XST_DEVICE_NOT_FOUND if the device was not * found in the configuration table in xsysace_g.c. * * @note * * We do not want to reset the configuration controller here since this could * cause a reconfiguration of the JTAG target chain, depending on how the * CFGMODEPIN of the device is wired. * ******************************************************************************/ XStatus XSysAce_Initialize(XSysAce *InstancePtr, u16 DeviceId) { XSysAce_Config *ConfigPtr; XASSERT_NONVOID(InstancePtr != NULL); InstancePtr->IsReady = 0; /* * Lookup configuration data in the device configuration table. * Use this configuration info down below when initializing this component. */ ConfigPtr = XSysAce_LookupConfig(DeviceId); if (ConfigPtr == (XSysAce_Config *)NULL) { return XST_DEVICE_NOT_FOUND; } /* * Set some default values for the instance data */ InstancePtr->BaseAddress = ConfigPtr->BaseAddress; InstancePtr->EventHandler = StubEventHandler; InstancePtr->NumRequested = 0; InstancePtr->NumRemaining = 0; InstancePtr->BufferPtr = NULL; /* * Put the device into 16-bit mode or 8-bit mode depending on compile-time * parameter */ #if (XPAR_XSYSACE_MEM_WIDTH == 16) XSysAce_RegWrite16(InstancePtr->BaseAddress + XSA_BMR_OFFSET, XSA_BMR_16BIT_MASK); #else XSysAce_RegWrite16(InstancePtr->BaseAddress + XSA_BMR_OFFSET, 0); #endif /* * Disable interrupts. Interrupts must be enabled by the user using * XSysAce_EnableInterrupt(). Put the interrupt request line in reset and * clear the interrupt enable bits. */ XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_RESETIRQ_MASK); XSysAce_mAndControlReg(InstancePtr->BaseAddress, ~(XSA_CR_DATARDYIRQ_MASK | XSA_CR_ERRORIRQ_MASK | XSA_CR_CFGDONEIRQ_MASK)); /* * Indicate the instance is now ready to use, initialized without error */ InstancePtr->IsReady = XCOMPONENT_IS_READY; return XST_SUCCESS; }
/** * * Enable System ACE interrupts. There are three interrupts that can be enabled. * The error interrupt enable serves as the driver's means to determine whether * interrupts have been enabled or not. The configuration-done interrupt is not * enabled here, instead it is enabled during a reset - which can cause a * configuration process to start. The data-buffer-ready interrupt is not enabled * here either. It is enabled when a read or write operation is started. The * reason for not enabling the latter two interrupts are because the status bits * may be set as a leftover of an earlier occurrence of the interrupt. * * @param InstancePtr is a pointer to the XSysAce instance to work on. * * @return * * None. * * @note * * None. * ******************************************************************************/ void XSysAce_EnableInterrupt(XSysAce * InstancePtr) { XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* By default, enable only the error interrupt */ XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_ERRORIRQ_MASK); /* Clear the reset on the interrupt line if it was in reset */ XSysAce_mAndControlReg(InstancePtr->BaseAddress, ~XSA_CR_RESETIRQ_MASK); }
/** * * Disable all System ACE interrupts and hold the interrupt request line of * the device in reset. * * @param InstancePtr is a pointer to the XSysAce instance that just interrupted. * * @return * * None. * * @note * * None. * ******************************************************************************/ void XSysAce_DisableInterrupt(XSysAce *InstancePtr) { XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* Put the interrupt request line in reset */ XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_RESETIRQ_MASK); /* Clear the interrupt enable bits */ XSysAce_mAndControlReg(InstancePtr->BaseAddress, ~(XSA_CR_DATARDYIRQ_MASK | XSA_CR_ERRORIRQ_MASK | XSA_CR_CFGDONEIRQ_MASK)); }
/** * * Reset the JTAG configuration controller. This comprises a reset of the JTAG * configuration controller and the CompactFlash controller (if it is currently * being accessed by the configuration controller). Note that the MPU controller * is not reset, meaning the MPU registers remain unchanged. The configuration * controller is reset then released from reset in this function. * * The CFGDONE status (and therefore interrupt) is cleared when the configuration * controller is reset. If interrupts have been enabled, we go ahead and enable * the CFGDONE interrupt here. This means that if and when a configuration * process starts as a result of this reset, an interrupt will be received when * it is complete. * * @param InstancePtr is a pointer to the XSysAce instance to be worked on. * * @return * * None. * * @note * * This function is not thread-safe. * ******************************************************************************/ void XSysAce_ResetCfg(XSysAce * InstancePtr) { XASSERT_VOID(InstancePtr != NULL); XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* Reset the configuration controller */ XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_CFGRESET_MASK); /* * If in interrupt mode, enable the CFGDONE and error interrupts. * A reset clears the CFGDONE and error statuses, so we're going to * re-enable the interrupts here so any new errors or CFGDONEs will be * caught. */ if (XSysAce_mIsIntrEnabled(InstancePtr->BaseAddress)) { XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_CFGDONEIRQ_MASK | XSA_CR_ERRORIRQ_MASK); } /* Release the reset of the configuration controller */ XSysAce_mAndControlReg(InstancePtr->BaseAddress, ~XSA_CR_CFGRESET_MASK); }
/** * * Initialize a specific XSysAce instance. The configuration information is * passed in as an argument and the driver instance data is initialized * appropriately. * * @param InstancePtr is a pointer to the XSysAce instance to be worked on. * @param Config is a reference to a structure containing information about a * specific SysAce device. This function initializes an InstancePtr object * for a specific device specified by the contents of Config. This function * can initialize multiple instance objects with the use of multiple calls * giving different Config information on each call. * @param EffectiveAddr is the device base address in the virtual memory address * space. The caller is responsible for keeping the address mapping * from EffectiveAddr to the device physical base address unchanged * once this function is invoked. Unexpected errors may occur if the * address mapping changes after this function is called. If address * translation is not used, use Config->BaseAddress for this parameters, * passing the physical address instead. * * @return * * XST_SUCCESS if successful. * * @note * * We do not want to reset the configuration controller here since this could * cause a reconfiguration of the JTAG target chain, depending on how the * CFGMODEPIN of the device is wired. * <br><br> * The Config pointer argument is not used by this function, but is provided * to keep the function signature consistent with other drivers. * ******************************************************************************/ XStatus XSysAce_CfgInitialize(XSysAce * InstancePtr, XSysAce_Config * Config, u32 EffectiveAddr) { XASSERT_NONVOID(InstancePtr != NULL); InstancePtr->IsReady = 0; /* * Set some default values for the instance data */ InstancePtr->BaseAddress = EffectiveAddr; InstancePtr->EventHandler = StubEventHandler; InstancePtr->NumRequested = 0; InstancePtr->NumRemaining = 0; InstancePtr->BufferPtr = NULL; /* * Put the device into 16-bit mode or 8-bit mode depending on compile-time * parameter */ #if (XPAR_XSYSACE_MEM_WIDTH == 16) XSysAce_RegWrite16(InstancePtr->BaseAddress + XSA_BMR_OFFSET, XSA_BMR_16BIT_MASK); #else XSysAce_RegWrite16(InstancePtr->BaseAddress + XSA_BMR_OFFSET, 0); #endif /* * Disable interrupts. Interrupts must be enabled by the user using * XSysAce_EnableInterrupt(). Put the interrupt request line in reset and * clear the interrupt enable bits. */ XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_RESETIRQ_MASK); XSysAce_mAndControlReg(InstancePtr->BaseAddress, ~(XSA_CR_DATARDYIRQ_MASK | XSA_CR_ERRORIRQ_MASK | XSA_CR_CFGDONEIRQ_MASK)); /* * Indicate the instance is now ready to use, initialized without error */ InstancePtr->IsReady = XCOMPONENT_IS_READY; return XST_SUCCESS; }
/** * * The interrupt handler for the System ACE driver. This handler must be * connected by the user to an interrupt controller or source. This function * does not save or restore context. * * This function continues reading or writing to the compact flash if such an * operation is in progress, and notifies the upper layer software through * the event handler once the operation is complete or an error occurs. On an * error, any command currently in progress is aborted. * * @param InstancePtr is a pointer to the XSysAce instance that just interrupted. * * @return * * None. * * @note * * None. * ******************************************************************************/ void XSysAce_InterruptHandler(void *InstancePtr) { u32 StatusReg; XSysAce *AcePtr = (XSysAce *) InstancePtr; XASSERT_VOID(InstancePtr != NULL); /* * Get the status in order to process each interrupt that has occurred */ StatusReg = XSysAce_mGetStatusReg(AcePtr->BaseAddress); /* * Reset the interrupt line to effectively clear the interrupt conditions. * We need to set the bit to clear the interrupts, then clear the bit so * that new interrupts can be generated. */ XSysAce_mOrControlReg(AcePtr->BaseAddress, XSA_CR_RESETIRQ_MASK); XSysAce_mAndControlReg(AcePtr->BaseAddress, ~XSA_CR_RESETIRQ_MASK); /* * Check for data buffer ready, which means an operation (either read or * write) is in progress. */ if (StatusReg & XSA_SR_DATABUFRDY_MASK) { /* * Handles the data buffer, and invokes the callback to the user for * data transfer completion. */ HandleDataBuffer(AcePtr, StatusReg); } /* * Check for completion of JTAG configuration and report the event up. * We only do this if the CFGDONE interrupt is enabled since the CFGDONE * status only gets cleared when the confguration controller is reset, * which we do not do unless requested by the user because it may cause * a configuration process to start. We could have gotten into this * interrupt handler by another interrupt, yet have a leftover CFGDONE * status from an earlier configuration process. */ if ((StatusReg & XSA_SR_CFGDONE_MASK) && (XSysAce_mGetControlReg(AcePtr->BaseAddress) & XSA_CR_CFGDONEIRQ_MASK)) { /* * Clear the bit indicating MPU is the source of configuration data * since we're done configuring from the MPU for now. Also clear the * force CFGMODE bit and the CFGSTART bit, basically undoing what was * done in XSysAce_ProgramChain(). Disable the interrupts since the * CFGDONE status does not get cleared unless a reset occurs - and in * the meantime we may get into this interrupt handler again. */ XSysAce_mAndControlReg(AcePtr->BaseAddress, ~(XSA_CR_CFGSEL_MASK | XSA_CR_CFGSTART_MASK | XSA_CR_CFGDONEIRQ_MASK | XSA_CR_DATARDYIRQ_MASK | XSA_CR_FORCECFGMODE_MASK)); AcePtr->EventHandler(AcePtr->EventRef, XSA_EVENT_CFG_DONE); } /* * Check for errors and report the event (the user is responsible for * retrieving and interpreting the errors). We only do this if the error * interrupt is enabled since the error status only gets cleared when the * CompactFlash or confguration controller is reset, which we do not do * because it may cause a configuration process to start. We could have * entered this interrupt handler by another interrupt and have a leftover * error status from a previous error. */ if ((StatusReg & (XSA_SR_CFGERROR_MASK | XSA_SR_CFCERROR_MASK)) && (XSysAce_mGetControlReg(AcePtr->BaseAddress) & XSA_CR_ERRORIRQ_MASK)) { /* Clear the transfer state to effectively abort the operation */ AcePtr->NumRequested = 0; AcePtr->NumRemaining = 0; AcePtr->BufferPtr = NULL; /* * Disable the error interrupt since the only way to clear the * error status is to reset the CF or the configuration controller, * neither of which we want to do here since the consequences may * be undesirable (i.e., may cause a reconfiguration). The user * will need to perform the reset based on the error event. */ XSysAce_mAndControlReg(AcePtr->BaseAddress, ~XSA_CR_ERRORIRQ_MASK); AcePtr->EventHandler(AcePtr->EventRef, XSA_EVENT_ERROR); } }
/** * * Attempt to lock access to the CompactFlash. The CompactFlash may be accessed * by the MPU port as well as the JTAG configuration port within the System ACE * device. This function requests exclusive access to the CompactFlash for the * MPU port. This is a non-blocking request. If access cannot be locked * (because the configuration controller has the lock), an appropriate status is * returned. In this case, the user should call this function again until * successful. * * If the user requests a forced lock, the JTAG configuration controller will * be put into a reset state in case it currently has a lock on the CompactFlash. * This effectively aborts any operation the configuration controller had in * progress and makes the configuration controller restart its process the * next time it is able to get a lock. * * A lock must be granted to the user before attempting to read or write the * CompactFlash device. * * @param InstancePtr is a pointer to the XSysAce instance to be worked on. * @param Force is a boolean value that, when set to TRUE, will force the MPU * lock to occur in the System ACE. When set to FALSE, the lock is * requested and the device arbitrates between the MPU request and * JTAG requests. Forcing the MPU lock resets the configuration * controller, thus aborting any configuration operations in progress. * * @return * * XST_SUCCESS if the lock was granted, or XST_DEVICE_BUSY if the lock was * not granted because the configuration controller currently has access to * the CompactFlash. * * @note * * If the lock is not granted to the MPU immediately, this function removes its * request for a lock so that a lock is not later granted at a time when the * application is (a) not ready for the lock, or (b) cannot be informed * asynchronously about the granted lock since there is no such interrupt event. * ******************************************************************************/ XStatus XSysAce_Lock(XSysAce * InstancePtr, u32 Force) { u32 IsLocked; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* * Check to see if the configuration controller currently has the lock */ IsLocked = (XSysAce_mGetStatusReg(InstancePtr->BaseAddress) & XSA_SR_CFGLOCK_MASK); if (Force) { /* * Reset the configuration controller if it has the lock. Per ASIC * designer, this eliminates a potential deadlock if the FORCELOCK and * LOCKREQ bits are both set and the RDYFORCFCMD is not set. */ if (IsLocked) { /* Reset the configuration controller */ XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_CFGRESET_MASK); } /* Force the MPU lock. The lock will occur immediately. */ XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_LOCKREQ_MASK | XSA_CR_FORCELOCK_MASK); } else { /* * Check to see if the configuration controller has the lock. If so, * return a busy status. */ if (IsLocked) { return XST_DEVICE_BUSY; } /* Request the lock, but do not force it */ XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_LOCKREQ_MASK); } /* * See if the lock was granted. Note that it is guaranteed to occur if * the user forced it. */ if (!XSysAce_mIsMpuLocked(InstancePtr->BaseAddress)) { /* Lock was not granted, so remove request and return a busy */ XSysAce_mAndControlReg(InstancePtr->BaseAddress, ~(XSA_CR_LOCKREQ_MASK | XSA_CR_FORCELOCK_MASK)); return XST_DEVICE_BUSY; } /* * Lock has been granted. * * If the configuration controller had the lock and has been reset, * go ahead and release it from reset as it will not be able to get * the lock again until the MPU lock is released. */ if (IsLocked && Force) { /* Release the reset of the configuration controller */ XSysAce_mAndControlReg(InstancePtr->BaseAddress, ~XSA_CR_CFGRESET_MASK); } return XST_SUCCESS; }
/** * * Write data to the CompactFlash. The user specifies the starting sector ID * and the number of sectors to be written. The minimum unit that can be written * to the CompactFlash is a sector, which is 512 bytes. * * In polled mode, this write is blocking. If there are other tasks in the * system that must run, it is best to keep the number of sectors to be written * to a minimum (e.g., 1). In interrupt mode, this write is non-blocking and an * event, XSA_EVENT_DATA_DONE, is returned to the user in the asynchronous * event handler when the write 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 to be worked on. * @param StartSector is the starting sector ID from where data will be written. * Sector IDs range from 0 (first sector) to 0x10000000. * @param NumSectors is the number of sectors to write. The range can be from * 1 to 256. * @param BufferPtr is a pointer to the data buffer to be written. This buffer * must have at least (512 * NumSectors) bytes. * * @return * * - XST_SUCCESS if the write was successful. In interrupt mode, this does not * mean the write is complete, only that it has begun. An event is returned * to the user when the write 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 write. 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_SectorWrite(XSysAce * InstancePtr, u32 StartSector, int NumSectors, u8 *BufferPtr) { u16 SectorCmd; int NumSent; int BytesToSend; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(NumSectors > 0 && NumSectors <= (XSA_SCCR_COUNT_MASK + 1)); XASSERT_NONVOID(BufferPtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* If a lock has not been granted, return an error */ if (!XSysAce_mIsMpuLocked(InstancePtr->BaseAddress)) { return XST_SYSACE_NO_LOCK; } /* See if the CF is ready for a command */ if (!XSysAce_mIsReadyForCmd(InstancePtr->BaseAddress)) { return XST_DEVICE_BUSY; } /* Write the sector ID (LBA) */ XSysAce_RegWrite32(InstancePtr->BaseAddress + XSA_MLR_OFFSET, StartSector); /* * Send the write command for the number of sectors specified */ SectorCmd = (NumSectors & XSA_SCCR_COUNT_MASK) | XSA_SCCR_WRITEDATA_MASK; XSysAce_RegWrite16(InstancePtr->BaseAddress + XSA_SCCR_OFFSET, SectorCmd); BytesToSend = XSA_CF_SECTOR_SIZE * NumSectors; /* * If in interrupt mode, set up the state variables and enable the * data-buffer-ready interrupt. We do this after the write command above * is done in order to guarantee that the interrupt occurs only after the * first data buffer write is done below (an interrupt may or may not occur * after the write command is issued) */ if (XSysAce_mIsIntrEnabled(InstancePtr->BaseAddress)) { /* * Set the state variables. We're going to send one data buffer here in * this routine, so adjust the buffer pointer and number remaining to * reflect this. */ InstancePtr->NumRequested = BytesToSend; InstancePtr->NumRemaining = BytesToSend - XSA_DATA_BUFFER_SIZE; InstancePtr->BufferPtr = BufferPtr + XSA_DATA_BUFFER_SIZE; /* Send only one data buffer in interrupt mode */ BytesToSend = XSA_DATA_BUFFER_SIZE; XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_DATARDYIRQ_MASK); } NumSent = XSysAce_WriteDataBuffer(InstancePtr->BaseAddress, BufferPtr, BytesToSend); if (NumSent != BytesToSend) { /* an error occurred, report this to the user */ return XST_FAILURE; } return XST_SUCCESS; }
/** * * 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 to be worked on. * @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; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(NumSectors > 0 && NumSectors <= (XSA_SCCR_COUNT_MASK + 1)); XASSERT_NONVOID(BufferPtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* If a lock has not been granted, return an error */ if (!XSysAce_mIsMpuLocked(InstancePtr->BaseAddress)) { return XST_SYSACE_NO_LOCK; } /* See if the CF is ready for a command */ if (!XSysAce_mIsReadyForCmd(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_mIsIntrEnabled(InstancePtr->BaseAddress)) { InstancePtr->NumRequested = BytesToRecv; InstancePtr->NumRemaining = BytesToRecv; InstancePtr->BufferPtr = BufferPtr; XSysAce_mOrControlReg(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_mIsIntrEnabled(InstancePtr->BaseAddress)) { int NumRead; /* Reset configuration controller (be sure to keep the lock) */ /* This breaks mvl, beware! */ /*XSysAce_mOrControlReg(InstancePtr->BaseAddress, XSA_CR_CFGRESET_MASK); */ NumRead = XSysAce_ReadDataBuffer(InstancePtr->BaseAddress, BufferPtr, BytesToRecv); /* Clear reset of configuration controller */ /* This breaks mvl, beware! */ /*XSysAce_mAndControlReg(InstancePtr->BaseAddress, ~(XSA_CR_CFGRESET_MASK)); */ if (NumRead != BytesToRecv) { /* an error occurred, report this to the user */ return XST_FAILURE; } } return XST_SUCCESS; }