/** * * Read the specified number of bytes from the data buffer of the ACE * controller. The data buffer, which is 32 bytes, can only be read two bytes * at a time. Once the data buffer is read, we wait for it to be filled again * before reading the next buffer's worth of data. * * @param BaseAddress is the base address of the device * @param BufferPtr is a pointer to a buffer in which to store data. * @param Size is the number of bytes to read * * @return * * The total number of bytes read, or 0 if an error occurred. * * @note * * If Size is not aligned with the size of the data buffer (32 bytes), this * function will read the entire data buffer, dropping the extra bytes on the * floor since the user did not request them. This is necessary to get the * data buffer to be ready again. * ******************************************************************************/ int XSysAce_ReadDataBuffer(Xuint32 BaseAddress, Xuint8 *BufferPtr, int Size) { int DataBytes; /* number of data bytes written */ int BufferBytes; Xuint16 Data; /* * Read data two bytes at a time. We need to wait for the data * buffer to be ready before reading the buffer. */ BufferBytes = 0; for (DataBytes = 0; DataBytes < Size;) { /* * If at any point during this read an error occurs, exit early */ if (XSysAce_mGetErrorReg(BaseAddress) != 0) { return 0; } if (BufferBytes == 0) { /* * Wait for CF data buffer to ready, then reset buffer byte count */ while ((XSysAce_mGetStatusReg(BaseAddress) & XSA_SR_DATABUFRDY_MASK) == 0); BufferBytes = XSA_DATA_BUFFER_SIZE; } /* * Need to read two bytes. Put the first one in the output buffer * because if we're here we know one more is needed. Put the second one * in the output buffer if there is still room, or just drop it on the * floor if the requested number of bytes have already been read. */ Data = XSysAce_RegRead16(BaseAddress + XSA_DBR_OFFSET); *BufferPtr++ = (Xuint8)Data; DataBytes++; if (DataBytes < Size) { /* Still more room in the output buffer */ *BufferPtr++ = (Xuint8)(Data >> 8); DataBytes++; } BufferBytes -= 2; }
static unsigned int XSysAce_GetCfgAddr(XSysAce * InstancePtr) { u32 Status; XASSERT_NONVOID(InstancePtr != NULL); XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY); Status = XSysAce_mGetControlReg(InstancePtr->BaseAddress); if (!(Status & XSA_CR_FORCECFGADDR_MASK)) Status = XSysAce_mGetStatusReg(InstancePtr->BaseAddress); return (unsigned int)((Status & XSA_SR_CFGADDR_MASK) >> XSA_CR_CFGADDR_SHIFT); }
/** * * 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; }