Esempio n. 1
0
/**
*
* 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;
}
/**
*
* 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);
}
Esempio n. 3
0
/**
*
* 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;
}
Esempio n. 4
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 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;
}
Esempio n. 5
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 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;
}
Esempio n. 6
0
/**
*
* 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;
}