/*
 * bl_tftp.c
 *
 *  Created on: 2014-6-21
 *      Author: ZB
 */


#include <string.h>
#include "sys_common.h"
#include "lwiplib.h"
#include "tftp.h"
#include "bl_tftp.h"
#include "bl_flash.h"
#include "bl_config.h"
#include "uartstdio.h"

uint32_t FlashDestination;
static uint8_t image_buf[512]={0};
extern tBoolean last_packet;
extern tBoolean image_download;

//
//TFTP write Image into Flash
//
static tTFTPError
TFTP_WriteImage(tTFTPConnection *psTFTP)
{
	uint32_t oReturnCheck=0;
    uint8_t ucBank=0;

    memcpy(image_buf+psTFTP->ulDataRemaining,psTFTP->pucData,psTFTP->ulDataLength);

    // check start address belong to which bank
    if(FlashDestination+(psTFTP->ulBlockNum - 1) * TFTP_BLOCK_SIZE < FLASH_BANK0_SIZE)
    {
    	ucBank = 0;
    }
    else
    {
    	ucBank = 1;
    }

    //
    // Program the new data.
    //
    if(last_packet)
    {
    	if((psTFTP->ulDataRemaining+psTFTP->ulDataLength)==TFTP_BLOCK_SIZE)
    	{
    		oReturnCheck = Fapi_BlockProgram(ucBank,FlashDestination+(psTFTP->ulBlockNum - 1) * TFTP_BLOCK_SIZE,(uint32_t)(image_buf),TFTP_BLOCK_SIZE);
    	}
    	else
    	{
    		oReturnCheck = Fapi_BlockProgram(ucBank,FlashDestination+(psTFTP->ulBlockNum - 1) * TFTP_BLOCK_SIZE,(uint32_t)(image_buf),(psTFTP->ulDataRemaining+psTFTP->ulDataLength)+4-(psTFTP->ulDataRemaining+psTFTP->ulDataLength)%4);
    		image_download=1;
    	}
    	memset(image_buf,0xFF,512);
    	last_packet=0;
    }

    //
    // Did all go as planned?
    //

    if(!oReturnCheck)
    {
        //
        // Everything is fine.
        //
        return(TFTP_OK);
    }
    else
    {
        //
        // Oops - we can't erase the block.  Report an error.
        //
        psTFTP->pcErrorString = "Flash write failure.";
        return(TFTP_ERR_NOT_DEFINED);
    }
}

//*****************************************************************************
//
// Read a block of data from the Flash
//
//*****************************************************************************
static tTFTPError
TFTP_ReadImage(tTFTPConnection *psTFTP)
{
	//Didn't develop the read function
	return(TFTP_ERR_NOT_DEFINED);;
}


//*****************************************************************************
//
// Signals that the TFTP connection is being closed down.
//
//*****************************************************************************
static void
TFTP_Close(tTFTPConnection *psTFTP)
{
    //
    // Nothing to do here currently.
    //
}


//*****************************************************************************
//
// Checks incoming TFTP request to determine if we want to handle it.
//
// \param psTFTP points to the TFTP connection instance structure for this
// request.
// \param bGet is \b true of the request is a GET (read) or \b false if it is
// a PUT (write).
// \param pucFileName points to a NULL terminated string containing the
// requested filename.
// \param tTFTPMode indicates the requested transfer mode, ASCII or binary.
//
// This function is called by the TFTP server whenever a new request is
// received.  It checks the passed filename to determine whether it is valid.
// If the filename is valid, the function sets fields \e ulDataRemaining, \e
// pfnGetData and \e pfnClose in the \e psTFTP structure for a GET request or
// fields \e pfnPutData, \e pfnClosebefore returning
// \e TFTP_OK to continue processing the request.
//
// This implementation supports requests for "eeprom" which will read or write
// the image stored in the serial flash device and "extflash" which will
// access an image stored in the flash provided by the Flash/SRAM/LCD daughter
// board if this is installed.
//
// \return Returns \e TFTP_OK if the request should be processed or any other
// TFTP error code otherwise.  In cases where \e TFTP_OK is not returned, the
// field psTFTP->pcErrorString may be set with an ASCII error string which
// will be returned to the TFTP client.
//
//*****************************************************************************
static tTFTPError
TFTP_Request(tTFTPConnection *psTFTP, tBoolean bGet, char *pucFileName,
                tTFTPMode eMode)
{
    uint32_t erase_length;

	FlashDestination = APP_START_ADDRESS;
	erase_length = FLASH_BANK0_SIZE - APP_START_ADDRESS;

#ifdef MSG_DEBUG
    UARTprintf("TFTP Request to Erase Flash... \n\r");
#endif

    //    if(Fapi_BlockErase( 0, FlashDestination, 0x00100000) && Fapi_BlockErase( 1, 0x00180000, 0x00180000))
    //    if(Fapi_BlockErase( 0, FlashDestination, erase_length) && Fapi_BlockErase( 1, 0x00180000, 0x00180000))
    if(Fapi_BlockErase( 0, FlashDestination, erase_length))
    {
    	psTFTP->pcErrorString = "Flash erase failure.";
    	return(TFTP_ERR_NOT_DEFINED);
    }

	//
	// Set the appropriate callback functions depending upon the
	// type of request received.
	//
	psTFTP->pfnClose = TFTP_Close;

	//
	// Is this a GET or a PUT request?
	//
	if(bGet)
	{
		//
		// GET request - fill in the image size and the data transfer
		// function pointer.
		//
		psTFTP->pfnGetData = TFTP_ReadImage;
	}
	else
	{
		//
		// PUT request - fill in the data transfer function pointer.
		//
		psTFTP->pfnPutData = TFTP_WriteImage;
	}

    //
    // If we get here, all is well and the transfer can continue.
    //
    return(TFTP_OK);
}

//*****************************************************************************
//
// Initializes the TFTP server supporting the HDK board.
// \return None.
//
//*****************************************************************************
void TFTPQSInit(void)
{
    //
    // Initialize the TFTP module and pass it our board-specific GET and PUT
    // request handler function pointer.
    //
    TFTPInit(TFTP_Request);
}

