/** * * Abort the CompactFlash operation currently in progress. * * 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 abort 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 * * According to the ASIC designer, the abort command has not been well tested. * ******************************************************************************/ int XSysAce_AbortCF(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 * * TODO: make sure this check works, or possibly the abort can be done * if it is not ready for a command (e.g., that's what we're aborting)? */ if (!XSysAce_mIsReadyForCmd(InstancePtr->BaseAddress)) { return XST_DEVICE_BUSY; } /* * Send the abort command */ XSysAce_RegWrite16(InstancePtr->BaseAddress + XSA_SCCR_OFFSET, XSA_SCCR_ABORT_MASK); return XST_SUCCESS; }
/** * * 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; }
/** * * A self-test that simply proves communication to the ACE controller from the * device driver by obtaining an MPU lock, verifying it, then releasing it. * * @param InstancePtr is a pointer to the XSysAce instance to be worked on. * * @return * * XST_SUCCESS if self-test passes, or XST_FAILURE if an error occurs. * * @note * * None. * ******************************************************************************/ int XSysAce_SelfTest(XSysAce * InstancePtr) { int Result; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); /* * Grab a lock (expect immediate success) */ Result = XSysAce_Lock(InstancePtr, TRUE); if (Result != XST_SUCCESS) { return Result; } /* * Verify the lock was retrieved */ if (!XSysAce_mIsMpuLocked(InstancePtr->BaseAddress)) { return XST_FAILURE; } /* * Release the lock */ XSysAce_Unlock(InstancePtr); /* * Verify the lock was released */ if (XSysAce_mIsMpuLocked(InstancePtr->BaseAddress)) { return XST_FAILURE; } /* * If there are currently any errors on the device, fail self-test */ if (XSysAce_mGetErrorReg(InstancePtr->BaseAddress) != 0) { return XST_FAILURE; } return XST_SUCCESS; }
/** * * 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; }
/** * * 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 to be worked on. * @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]; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(ParamPtr != 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, 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_mIsIntrEnabled(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_mOrControlReg(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_mAndControlReg(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; }
/** * * Program the target FPGA chain through the configuration JTAG port. This * allows the user to program the devices on the target FPGA chain from the MPU * port instead of from CompactFlash. The user specifies a buffer and the number * of bytes to write. The buffer should be equivalent to an ACE (.ace) file. * * Note that when loading the ACE file via the MPU port, the first sector of the * ACE file is discarded. The CF filesystem controller in the System ACE device * knows to skip the first sector when the ACE file comes from the CF, but the * CF filesystem controller is bypassed when the ACE file comes from the MPU * port. For this reason, this function skips the first sector of the buffer * passed in. * * In polled mode, the write is blocking. In interrupt mode, the write is * non-blocking and an event, XSA_EVENT_CFG_DONE, is returned to the user in * the asynchronous event handler when the configuration is complete. * * 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 BufferPtr is a pointer to a buffer that will be used to program * the configuration JTAG devices. * @param NumBytes is the number of bytes in the buffer. We assume that there * is at least one sector of data in the .ace file, which is the * information sector. * * @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_FAILURE if an error occurred during the write. The user should call * XSysAce_GetErrors() to determine the cause of the error. * * @note * * None. * * @internal * * The System ACE controller has a 32-byte buffer which holds data. The entire * buffer must be written to ensure that it gets sent to the configuration * JTAG port. If the number of bytes specified by the user is not a multiple * of 32, the driver will pad the remaining bytes of the System ACE buffer with * zeroes in order to write the entire buffer. * ******************************************************************************/ XStatus XSysAce_ProgramChain(XSysAce * InstancePtr, u8 * BufferPtr, int NumBytes) { u32 ControlMask; int BytesToSend; int NumSent; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(BufferPtr != NULL); XASSERT_NONVOID(NumBytes > XSA_CF_SECTOR_SIZE); 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; } /* * Set up the configuration controller to use the MPU port as the * source of configuration data (instead of the CF). The following * control flow comes directly from the System ACE specification, except * the reset was moved to after the other control register bits are set. * Putting it into reset before the bits are set seemed to produce * configuration errors occasionally. */ ControlMask = XSysAce_mGetControlReg(InstancePtr->BaseAddress); /* Select MPU as the source */ ControlMask |= XSA_CR_CFGSEL_MASK; XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask); /* Tell controller to wait for start bit from MPU */ ControlMask |= XSA_CR_FORCECFGMODE_MASK; ControlMask &= ~XSA_CR_CFGMODE_MASK; XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask); /* Set the start bit */ ControlMask |= XSA_CR_CFGSTART_MASK; XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask); /* Put the configuration controller into a reset condition */ ControlMask |= XSA_CR_CFGRESET_MASK; XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask); /* Clear the reset condition, which starts the process */ ControlMask &= ~XSA_CR_CFGRESET_MASK; XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask); /* * Set up number of bytes to send. Default to the entire buffer, which * will be true in polled mode. In interrupt mode, modify this value to * send only one data buffer of data. Always skip the first sector per * the comment above. */ BytesToSend = NumBytes - XSA_CF_SECTOR_SIZE; /* * The number of bytes to write depends on interrupt or polled mode */ if (XSysAce_mIsIntrEnabled(InstancePtr->BaseAddress)) { /* * In interrupt mode, so enable the data-buffer-ready and * configuration-done interrupts. Also, set up the state variables for * the interrupt handler to transfer the remaining data after the * initial write below. We need to write one data buffer here in this * function in order to cause the data-buffer-ready interrupt to occur * for subsequent writes. */ ControlMask |= XSA_CR_DATARDYIRQ_MASK | XSA_CR_CFGDONEIRQ_MASK; XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask); /* Send only one data buffer to begin with (if there is that much) */ if (BytesToSend > XSA_DATA_BUFFER_SIZE) { BytesToSend = XSA_DATA_BUFFER_SIZE; } /* * Setup state variables for the interrupt handler. Skip the first * sector per the comment above, and also skip the first data buffer * since it is written below. */ InstancePtr->NumRequested = NumBytes - XSA_CF_SECTOR_SIZE; InstancePtr->BufferPtr = BufferPtr + XSA_CF_SECTOR_SIZE + BytesToSend; InstancePtr->NumRemaining = NumBytes - XSA_CF_SECTOR_SIZE - BytesToSend; } NumSent = XSysAce_WriteDataBuffer(InstancePtr->BaseAddress, BufferPtr + XSA_CF_SECTOR_SIZE, BytesToSend); if (NumSent != BytesToSend) { /* an error occurred, report this to the user */ return XST_FAILURE; } /* * If in polled mode, restore the control register to the way it was */ if (!XSysAce_mIsIntrEnabled(InstancePtr->BaseAddress)) { /* * Unselect MPU as the source, tell controller to use CFGMODE pin, * and clear the start bit. */ ControlMask &= ~(XSA_CR_CFGSEL_MASK | XSA_CR_FORCECFGMODE_MASK | XSA_CR_CFGSTART_MASK); XSysAce_mSetControlReg(InstancePtr->BaseAddress, ControlMask); } return XST_SUCCESS; }