/**HEADER********************************************************************
* 
* Copyright (c) 2010 Avnet Japan Co.,Ltd (NIKE Borad Project.)
* All Rights Reserved
*
*************************************************************************** 
*
* $FileName: P5Q_spi_mcf52xx.c$
* $Version : 0.1.0.0$
* $Date    : Jan-29-2010$
*
* Comments:
*
*
*END************************************************************************/
#include "mqx.h"
#include "bsp.h"
#include "io_prv.h"
#include "fio_prv.h"
//#include "timer.h"
#include "../P5Q_spi.h"
#include "../P5Q_spi_prv.h"

#include "P5Q_spi_mcf52xx.h"
#include "P5Q_spi_mcf52xx_prv.h"
#include "iomemprv.h"

/* ------------------------------------------------------------------ 
   --- macro definition                                           --- 
   ------------------------------------------------------------------ */

#define QSPI_CHIP_SELECT1		0x0E
#define E_OK					0

//#define P5Q_DISK_SIZE		((1024l*1024l*7l))
#define P5Q_DISK_SIZE		((1024l*1024l*15l))

//#define MEMORY_W25Q64CV				1
#define MEMORY_P5Q					1


#ifdef MEMORY_P5Q
#define FLASH_CMD_RDID		0x9F
#define FLASH_CMD_WREN		0x06
#define FLASH_CMD_WRDI		0x04
#define FLASH_CMD_RDSR		0x05
#define FLASH_CMD_SE		0xD8
#define FLASH_CMD_BE		0xC7
#define FLASH_CMD_READ		0x03
#define FLASH_CMD_WRITE		0x22
#endif

#ifdef MEMORY_W25Q64CV
#define FLASH_CMD_RDID		0x9F
#define FLASH_CMD_WREN		0x06
#define FLASH_CMD_WRDI		0x04
#define FLASH_CMD_RDSR		0x05
#define FLASH_CMD_SE		0xD8
#define FLASH_CMD_BE		0xC7
#define FLASH_CMD_READ		0x03
#define FLASH_CMD_WRITE		0x02
#endif



/* ------------------------------------------------------------------ 
   --- structure body definition                                  --- 
   ------------------------------------------------------------------ */


/* 宣言：P5Q_STATISTICS */
typedef struct
{
	uint_32	p5q_write_count_max;
}P5Q_STATISTICS, *PP5Q_STATISTICS;


/* ------------------------------------------------------------------ 
   --- variable definition                                        --- 
   ------------------------------------------------------------------ */

P5Q_STATISTICS	p5q_statistics;


/* ------------------------------------------------------------------ 
   --- prototype declaration                                      --- 
   ------------------------------------------------------------------ */

extern uint_32 _mcf52xx_P5Q_spi_init(FILE_DEVICE_STRUCT_PTR, pointer _PTR_, char_ptr);
extern uint_32 _mcf52xx_P5Q_spi_deinit(MCF52XX_P5Q_SPI_INIT_STRUCT_PTR, MCF52XX_P5Q_SPI_INFO_STRUCT_PTR);
extern int_32  _mcf52xx_P5Q_spi_ioctl(FILE_DEVICE_STRUCT_PTR, uint_32, _mqx_uint_ptr);

extern int_32  _mcf52xx_P5Q_spi_read(FILE_DEVICE_STRUCT_PTR , uchar_ptr, _mqx_int);
extern int_32  _mcf52xx_P5Q_spi_write(FILE_DEVICE_STRUCT_PTR, uchar_ptr, _mqx_int);

int_32  _mcf52xx_pcm_P5Q_cmd_rdid(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar *data);
int_32  _mcf52xx_pcm_P5Q_cmd_wren(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr);
int_32  _mcf52xx_pcm_P5Q_cmd_wrdi(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr);

int_32  _mcf52xx_pcm_P5Q_cmd_rdsr(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar *status);
int_32  _mcf52xx_pcm_P5Q_cmd_se(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uint_32 addr);

int_32  _mcf52xx_pcm_P5Q_cmd_read(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uint_32 addr, uchar *data, int_32 size);
int_32  _mcf52xx_pcm_P5Q_cmd_pp_lp(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uint_32 addr, uchar *data, int_32 size);
int_32  _mcf52xx_pcm_P5Q_cmd_pp_baw(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uint_32 addr, uchar *data, int_32 size);

int_32  _mcf52xx_pcm_P5Q_rx(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar *cmd_data, int_32 cmd_size, uchar *data, int_32 size);
int_32  _mcf52xx_pcm_P5Q_tx(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar *data, int_32 size);

int_32 _mcf52xx_P5Q_spi_rx(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar_ptr buffer, int_32 size);
int_32 _mcf52xx_P5Q_spi_tx(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar_ptr buffer, int_32 size );

int_32 _mcf52xx_P5Q_spi_rx_cmd(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar cmd_data, uchar_ptr buffer, int_32 size);
void *memcpy(void *dest, const void *source, _mem_size n);

pointer _bsp_get_qspi_base_address(uint_8);
uint_32 _bsp_get_qspi_vector(uint_8);

void p5q_printf_dump_byte(uint_32 addr, uint_32 size );
int_32  _mcf52xx_pcm_P5Q_cmd_be(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr);



/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    : p5q_printf_dump_byte
* Returned Value   : Address upon success, NULL upon failure
* Comments         :
*    This function returns the base register address of the corresponding SPI
*
*END*----------------------------------------------------------------------*/
void p5q_printf_dump_byte(uint_32 addr, uint_32 size )
{
	unsigned char *pdmup;
	int i;

	pdmup = (unsigned char*)addr;

	for ( i=0; i<size; i++ ){
		if ( (i%16) == 0 ){
			printf("%08x:", &pdmup[i]);
		}

		printf("%02x ", pdmup[i]);

		if ((i%16) == 15){
			printf(";\n");
		}
	}
}



/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    : _bsp_get_qspi_base_address
* Returned Value   : Address upon success, NULL upon failure
* Comments         :
*    This function returns the base register address of the corresponding SPI
*
*END*----------------------------------------------------------------------*/
pointer _bsp_get_qspi_base_address(uint_8 dev_num)
{
	if (dev_num > 0){
		return NULL;
	}

	return (pointer)&(((VMCF5225_STRUCT_PTR)_PSP_GET_IPSBAR())->QSPI);
}

/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    : _bsp_get_qspi_vector
* Returned Value   : Vector number upon success, 0 upon failure
* Comments         :
*    This function returns desired interrupt vector number for specified SPI
*
*END*----------------------------------------------------------------------*/
uint_32 _bsp_get_qspi_vector(uint_8 dev_num)
{
	if (dev_num > 0){
		return 0;
	}

	return MCF5225_INT_QSPI;
}

                       
/*FUNCTION*-------------------------------------------------------------------
* 
* Function Name    : _mcf52xx_P5Q_spi_install
* Input Value      :
      [IN] A string that identifies the device for fopen 	: char_ptr  identifier
      [IN] The I/O init data pointer 						: pointer   init_data_ptr

* Returned Value   : uint_32 a task error code or MQX_OK
* Comments         :
*    Install an QSPI device.
*
*END*----------------------------------------------------------------------*/
uint_32 _mcf52xx_P5Q_spi_install( char_ptr identifier, pointer init_data_ptr)
{

   return _io_P5Q_spi_install(identifier,
      (uint_32 (_CODE_PTR_)(pointer, pointer _PTR_, char_ptr))_mcf52xx_P5Q_spi_init,
      (uint_32 (_CODE_PTR_)(pointer, pointer))_mcf52xx_P5Q_spi_deinit,
      (int_32 (_CODE_PTR_)(pointer, char_ptr, _mqx_int))_mcf52xx_P5Q_spi_read,
      (int_32 (_CODE_PTR_)(pointer, char_ptr, _mqx_int))_mcf52xx_P5Q_spi_write,
      (int_32 (_CODE_PTR_)(pointer, uint_32, _mqx_uint_ptr))_mcf52xx_P5Q_spi_ioctl,
      init_data_ptr);
}



/*FUNCTION****************************************************************
* 
* Function Name    : _mcf52xx_P5Q_spi_init  
* Input Value      :
   [IN] the initialization information for the device being opened 	: MCF52XX_P5Q_SPI_INIT_STRUCT_PTR  init_io_dev_ptr
   [OUT] the address to store device specific information 			: pointer _PTR_  io_info_ptr_ptr
   [IN] the rest of the name of the device opened 					: char_ptr       open_name_ptr

* Returned Value   : uint_32 a QSPI error code or QSPI_OK
* Comments         :
*    This function initializes the QSPI module 
*
*END*********************************************************************/
uint_32 _mcf52xx_P5Q_spi_init(FILE_DEVICE_STRUCT_PTR fd_ptr, pointer _PTR_ io_info_ptr_ptr, char_ptr open_name_ptr)
{
	VMCF5XXX_QSPI_STRUCT_PTR         qspi_ptr;
	IO_DEVICE_STRUCT_PTR             io_dev_ptr;
	IO_P5Q_SPI_DEVICE_STRUCT_PTR     dev_ptr;
	MCF52XX_P5Q_SPI_INFO_STRUCT_PTR  io_info_ptr;
	MCF52XX_P5Q_SPI_INIT_STRUCT_PTR  init_io_dev_ptr;
	uint_32                          div;
	uint_32                          result = QSPI_OK;
	uint_16                          tmp_reg;
	static uchar                     ID_data[3];

	io_dev_ptr      = (IO_DEVICE_STRUCT_PTR)fd_ptr->DEV_PTR;
	dev_ptr         = (IO_P5Q_SPI_DEVICE_STRUCT_PTR)(io_dev_ptr->DRIVER_INIT_PTR);
	init_io_dev_ptr = (MCF52XX_P5Q_SPI_INIT_STRUCT_PTR)dev_ptr->DEV_INIT_DATA_PTR;
	qspi_ptr        = _bsp_get_qspi_base_address(0);

	/* QSPI board specific initialization */

	/* Initialize internal data */
	io_info_ptr = (MCF52XX_P5Q_SPI_INFO_STRUCT _PTR_)_mem_alloc_system_zero((uint_32)sizeof(MCF52XX_P5Q_SPI_INFO_STRUCT));

#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
	if (io_info_ptr == NULL) {
		return(MQX_OUT_OF_MEMORY);
	}
#endif

	*io_info_ptr_ptr = io_info_ptr;

	io_info_ptr->INIT       = *init_io_dev_ptr;
	io_info_ptr->INT_BITS   = 0;
	io_info_ptr->BUFFER     = NULL;
	io_info_ptr->INTERRUPTS = 0;
	io_info_ptr->RX_PACKETS = 0;
	io_info_ptr->TX_PACKETS = 0;
	io_info_ptr->TX_ABORT   = 0;

	p5q_statistics.p5q_write_count_max = 0;

	/* Master mode only */
	qspi_ptr->QMR = QSPI_QMR_MSTR;

	/* Set the QSPI clock baud rate divider */
	//div = BSP_SYSTEM_CLOCK / (2 * init_io_dev_ptr->BAUD_RATE);
	div = BSP_SYSTEM_CLOCK / (2 * 20000000l);

#ifdef MQX_CHECK_ERRORS
	/* Check for the divider value */
	if((div > 255) || (div < 2)) {
		_mem_free(io_info_ptr);
		return QSPI_BRG_FAILD;
	}
#endif

	/* Program the value divider */
	qspi_ptr->QMR |= QSPI_QMR_BAUD(div);

	/* Inactive state of QSPI_CLK = logic 1 */
	qspi_ptr->QMR |= QSPI_QMR_CPOL;
	/* QSPI_CLK transitions begining of bit timing */
	qspi_ptr->QMR |= QSPI_QMR_CPHA;

	/* Data output high impedance disable (default value) */
  	qspi_ptr->QMR &= ~QSPI_QMR_DOHIE;

	/* Data output high impedance disable (default value) */
	qspi_ptr->QWR |= QSPI_QWR_CSIV;

	qspi_ptr->QDLYR = 0;

	/* Set delay after transfer to be standard: 17/(fsys/2) */
//	qspi_ptr->QDLYR |= QSPI_QDLYR_QCD(0x0004);
	qspi_ptr->QDLYR |= QSPI_QDLYR_QCD(0x0001);

	/* 
	** set delay chip select to QSPI clock 
	** to be standard: 1/2 the QSPI_CLK period 
	*/
//	qspi_ptr->QDLYR |= QSPI_QDLYR_DTL(0x0004);
	qspi_ptr->QDLYR |= QSPI_QDLYR_DTL(0x0001);

	/* Enable write collision, Abort bus errors */
	qspi_ptr->QIR = (QSPI_QIR_WCEFB | QSPI_QIR_ABRTB | QSPI_QIR_ABRTL);

	/* Clear all interrupts */
	tmp_reg = QSPI_QIR_WCEF | QSPI_QIR_ABRT | QSPI_QIR_SPIF;
	qspi_ptr->QIR &= ~(tmp_reg);

	/* Set transfer size to default (8 bits) */
	qspi_ptr->QMR |= QSPI_QMR_BITS(QSPI_QMR_8_BITS);

	/* Configure GPIO pins */
	_bsp_qspi_io_init(QSPI_CHIP_SELECT1);

	_mcf52xx_pcm_P5Q_cmd_rdid(0,&ID_data[0]);

	return (result);
}


/*FUNCTION****************************************************************
* 
* Function Name    : _mcf52xx_P5Q_spi_deinit  
* Input Value      :
   [IN] the initialization information for the device being opened 	: MCF52XX_P5Q_SPI_INIT_STRUCT_PTR int_io_dev_ptr,
   [IN] the address of the device specific information 				: MCF52XX_P5Q_SPI_INFO_STRUCT_PTR io_info_ptr

* Returned Value   : uint_32 a QSPI error code or QSPI_OK
* Comments         :
*    This function de-initializes the QSPI module 
*
*END*********************************************************************/
uint_32 _mcf52xx_P5Q_spi_deinit(MCF52XX_P5Q_SPI_INIT_STRUCT_PTR int_io_dev_ptr, MCF52XX_P5Q_SPI_INFO_STRUCT_PTR io_info_ptr)
{
	VMCF5XXX_QSPI_STRUCT_PTR     qspi_ptr;
	TIME_STRUCT                  time;
	uint_32                      milliseconds;

	qspi_ptr = _bsp_get_qspi_base_address(0);
	 
	/* wait while qspi is busy */
	qspi_ptr->QWR |= QSPI_QWR_HALT;

	/* Disable the QSPI */
	qspi_ptr->QMR |= QSPI_QMR_DOHIE;

	return (QSPI_OK);
}


uint_32		TestAddr;
uchar		Testdata[16];


/*FUNCTION****************************************************************
* 
* Function Name    : _mcf52xx_P5Q_spi_ioctl
* Input Value      :
      [IN] the file handle for the device  : FILE_DEVICE_STRUCT_PTR fd_ptr,
      [IN] The command to perform          : uint_32 cmd,
      [IN] Parameters for the command      : uint_32_ptr param_ptr

* Returned Value   : QSPI_OK or a QSPI error code.
* Comments         : 
*    This function performs miscellaneous services for
*    the QSPI I/O device.  
*
*END*********************************************************************/
int_32 _mcf52xx_P5Q_spi_ioctl(FILE_DEVICE_STRUCT_PTR fd_ptr, uint_32 cmd, uint_32_ptr param_ptr)
{
	IO_DEVICE_STRUCT_PTR               io_dev_ptr;
	IO_P5Q_SPI_DEVICE_STRUCT_PTR       dev_ptr;
	MCF52XX_P5Q_SPI_INFO_STRUCT_PTR    io_info_ptr;
	VMCF5XXX_QSPI_STRUCT_PTR           qspi_ptr;
	volatile uint_32                   tstatus;
	volatile uint_32                   tmp_cs;
	volatile uint_32                   state_lev;
	_mqx_int                           i;
	uint_32                            result = QSPI_OK;
	_mem_size_ptr                      mparam_ptr;
	_mqx_uint_ptr                      uparam_ptr;
	uint_32_ptr                        u32param_ptr;

	uint_32                            *AcessAddr;
	uchar                              *Acessdata;
	PCM_SPI_MAMORY_IO                  *pPCM_mam;


//   printf("p5q dev ioctl = cmd %x \n", cmd);


	io_dev_ptr = (IO_DEVICE_STRUCT_PTR)fd_ptr->DEV_PTR;
	dev_ptr = (pointer)io_dev_ptr->DRIVER_INIT_PTR;
	io_info_ptr  = dev_ptr->DEV_INFO_PTR;

	dev_ptr->BASE_ADDR = 0;
	dev_ptr->SIZE = P5Q_DISK_SIZE;
	qspi_ptr = _bsp_get_qspi_base_address(0);

	switch (cmd) {
      case IO_IOCTL_QSPI_DISABLE_DEVICE:
         qspi_ptr->QWR |= QSPI_QWR_HALT;
         break;

      case IO_IOCTL_QSPI_ENABLE_DEVICE:
         qspi_ptr->QWR &= ~QSPI_QWR_HALT;
         break;

		case IO_IOCTL_QSPI_SET_TRANSFER_SIZE:
			if (*param_ptr == QSPI_TRANSFER_8_BITS){
				/* Set transfer size to default (8 bits) */
				qspi_ptr->QMR |= QSPI_QMR_BITS(QSPI_QMR_8_BITS);
			}

			if (*param_ptr == QSPI_TRANSFER_16_BITS){
				/* Set transfer size to max. (16 bits) */
				qspi_ptr->QMR &= 0xC3FF;
			}
			break;

		case IO_IOCTL_QSPI_GET_LAST_COMMAND_COMPLETE:
			tstatus = 0;
			tstatus = (qspi_ptr->QWR & 0x00F0);
			*param_ptr = tstatus;
			break;

		case IO_IOCTL_SERIAL_GET_STATS:
			*param_ptr++ = io_info_ptr->INTERRUPTS;
			*param_ptr++ = io_info_ptr->RX_PACKETS;
			*param_ptr++ = io_info_ptr->TX_PACKETS;
			*param_ptr++ = io_info_ptr->TX_ABORT;
			break;

		case IO_IOCTL_SERIAL_CLEAR_STATS:
			io_info_ptr->INTERRUPTS = 0;
			io_info_ptr->RX_PACKETS = 0;
			io_info_ptr->TX_PACKETS = 0;
			io_info_ptr->TX_ABORT = 0;
			break;

		/* special ioctl */
		case IO_IOCTL_QSPI_SET_ADDR:
			AcessAddr = (uint_32*)param_ptr;
			TestAddr = *AcessAddr;
			break;

		case IO_IOCTL_QSPI_GET_ADDR:
			AcessAddr = (uint_32*)param_ptr;
			*AcessAddr = TestAddr;
			break;

		case IO_IOCTL_QSPI_SET_MEM:
			Acessdata = (uchar*)param_ptr;
			Testdata[0] = *Acessdata;
			_mcf52xx_pcm_P5Q_cmd_pp_baw(dev_ptr, TestAddr, &Testdata[0], 1);
			break;

		case IO_IOCTL_QSPI_GET_MEM:
			Acessdata = (uchar*)param_ptr;
			_mcf52xx_pcm_P5Q_cmd_read(dev_ptr, TestAddr, &Testdata[0], 1);
			*Acessdata = Testdata[0];
			break;

		case IO_IOCTL_QSPI_BLOCK_SET_MEM:
			pPCM_mam = (PCM_SPI_MAMORY_IO*)param_ptr;
			_mcf52xx_pcm_P5Q_cmd_pp_baw(dev_ptr, pPCM_mam->addr, pPCM_mam->data, pPCM_mam->size);
			break;

		case IO_IOCTL_QSPI_BLOCK_GET_MEM:
			pPCM_mam = (PCM_SPI_MAMORY_IO*)param_ptr;
			_mcf52xx_pcm_P5Q_cmd_read(dev_ptr, pPCM_mam->addr, pPCM_mam->data, pPCM_mam->size);
			break;

		case IO_IOCTL_QSPI_SCTOR_ERASE:
			AcessAddr = (uint_32*)param_ptr;
			TestAddr = *AcessAddr;
			_mcf52xx_pcm_P5Q_cmd_se(dev_ptr, TestAddr);
			break;


		case IO_IOCTL_QSPI_BLOCK_ERASE:
			_mcf52xx_pcm_P5Q_cmd_be(dev_ptr);
			break;

		/* Start CR 810 */
		case IO_IOCTL_GET_BLOCK_SIZE:
			uparam_ptr  = (_mqx_uint_ptr)param_ptr;
			*uparam_ptr = IO_MEM_BLOCK_SIZE;
			break;
		case IO_IOCTL_DEVICE_IDENTIFY:
			u32param_ptr  = (uint_32_ptr)param_ptr;
		 	u32param_ptr[IO_IOCTL_ID_PHY_ELEMENT]  = IO_DEV_TYPE_PHYS_MEMIO;
			u32param_ptr[IO_IOCTL_ID_LOG_ELEMENT]  = IO_DEV_TYPE_LOGICAL_MFS;
//			u32param_ptr[IO_IOCTL_ID_ATTR_ELEMENT] = IO_MEM_ATTRIBS;
			u32param_ptr[IO_IOCTL_ID_ATTR_ELEMENT] = IO_DEV_ATTR_ERASE | IO_DEV_ATTR_POLL
																| IO_DEV_ATTR_READ | IO_DEV_ATTR_REMOVE
																| IO_DEV_ATTR_SEEK | IO_DEV_ATTR_WRITE;

//			if (handle_ptr->BLOCK_MODE) {
//				u32param_ptr[IO_IOCTL_ID_ATTR_ELEMENT] |= IO_DEV_ATTR_BLOCK_MODE;
//			}
			break;

		case IO_IOCTL_GET_NUM_SECTORS:
			/* return number of sectors, needed for MFS format */
			mparam_ptr = (_mem_size_ptr)param_ptr;
			*mparam_ptr = (_mem_size)dev_ptr->SIZE / IO_MEM_BLOCK_SIZE;

//			printf("P5Q: %d / %d \n", dev_ptr->SIZE, IO_MEM_BLOCK_SIZE);
//			printf("P5Q: IO_IOCTL_GET_NUM_SECTORS size %d\n", *mparam_ptr);


			break;

		default:
			result = IO_ERROR_INVALID_IOCTL_CMD;
			break;

	}

	return(result);
}



/*FUNCTION****************************************************************
* 
* Function Name    :_mcf52xx_P5Q_spi_read
* Returned Value   : Returns the number of bytes received or QSPI error   
* Comments         : 
*   Reads the data into provided array.
*
*END*********************************************************************/
int_32 _mcf52xx_P5Q_spi_read(FILE_DEVICE_STRUCT_PTR fd_ptr, uchar_ptr buffer, int_32 size)
{
	IO_DEVICE_STRUCT_PTR             io_dev_ptr;
	IO_P5Q_SPI_DEVICE_STRUCT_PTR     dev_ptr;
	uchar_ptr                        src_ptr;
	_file_size                       fsize;

	io_dev_ptr = (IO_DEVICE_STRUCT_PTR)fd_ptr->DEV_PTR;
	dev_ptr = (IO_P5Q_SPI_DEVICE_STRUCT_PTR)io_dev_ptr->DRIVER_INIT_PTR;

	dev_ptr->BASE_ADDR = 0;
	dev_ptr->SIZE = P5Q_DISK_SIZE;
	fsize = dev_ptr->SIZE;


	if( fd_ptr->LOCATION >= fsize) {
		fd_ptr->FLAGS |= IO_FLAG_AT_EOF;
		return 0;
	}

	src_ptr = fd_ptr->LOCATION + dev_ptr->BASE_ADDR;
	if ( (src_ptr + size) > (dev_ptr->BASE_ADDR + fsize) ) {
		fd_ptr->FLAGS |= IO_FLAG_AT_EOF;
		size = (_mqx_int)((dev_ptr->BASE_ADDR + fsize) - (dev_ptr->BASE_ADDR + fd_ptr->LOCATION) + 1);
	}

//	_lwsem_wait(&dev_ptr->LWSEM);

//	_mem_copy((pointer)src_ptr, (pointer)buffer, (_mem_size)size);
	_mcf52xx_pcm_P5Q_cmd_read(dev_ptr, (uint_32)src_ptr, (uchar*)buffer, size);

//	printf("P5Q[read]: addr %x - %x \n", src_ptr, size);
//	p5q_printf_dump_byte((uint_32)buffer,(uint_32) size);

	fd_ptr->LOCATION += (_file_size)size;

//	_lwsem_post(&dev_ptr->LWSEM);

	return size;
}




/*FUNCTION****************************************************************
* 
* Function Name    : _mcf52xx_P5Q_spi_write
* Returned Value   : return number of byte transmitted or QSPI error code
* Comments         : 
*   Writes the provided data buffer and loops until transmission complete
*
*END*********************************************************************/
int_32 _mcf52xx_P5Q_spi_write(FILE_DEVICE_STRUCT_PTR fd_ptr, uchar_ptr buffer, int_32 size)
{
	IO_DEVICE_STRUCT_PTR             io_dev_ptr;
	IO_P5Q_SPI_DEVICE_STRUCT_PTR     dev_ptr;
	uchar_ptr                        dest_ptr;
	_file_size                       fsize;

	io_dev_ptr = (IO_DEVICE_STRUCT_PTR)fd_ptr->DEV_PTR;
	dev_ptr = (IO_P5Q_SPI_DEVICE_STRUCT_PTR)io_dev_ptr->DRIVER_INIT_PTR;

	dev_ptr->BASE_ADDR = 0;
	dev_ptr->SIZE = P5Q_DISK_SIZE;
	fsize = dev_ptr->SIZE;

	if(fd_ptr->LOCATION >= fsize) {
		fd_ptr->FLAGS |= IO_FLAG_AT_EOF;
		return 0;
	}

	dest_ptr = fd_ptr->LOCATION + dev_ptr->BASE_ADDR;
	if ( (dest_ptr + size) > (dev_ptr->BASE_ADDR + fsize) ){
		fd_ptr->FLAGS |= IO_FLAG_AT_EOF;
		size = (_mqx_int)((dev_ptr->BASE_ADDR + fsize) - (dev_ptr->BASE_ADDR + fd_ptr->LOCATION) + 1);
	}

//	_lwsem_wait(&dev_ptr->LWSEM);
//	_mem_copy((pointer)buffer, (pointer)dest_ptr, (_mem_size)size);

//	printf("P5Q[write]: addr %x - %x \n", dest_ptr, size);
//	p5q_printf_dump_byte((uint_32)buffer,(uint_32) size);

	_mcf52xx_pcm_P5Q_cmd_pp_baw(dev_ptr,(uint_32)dest_ptr,(uchar*)buffer, size);

	fd_ptr->LOCATION += (_file_size)size;
//	_lwsem_post(&dev_ptr->LWSEM);

	return size;
}





static uchar recv_buffer[16];
static uchar send_buffer[16];


/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  _mcf52xx_pcm_P5Q_cmd_rdid
* Returned Value   :  int_32 error code
* Comments  :  
*
*END*---------------------------------------------------------------------*/

int_32  _mcf52xx_pcm_P5Q_cmd_rdid(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar *data)
{
	uint_32	i;
	uint_32	rtn = 0;

	send_buffer[0] = FLASH_CMD_RDID;
	rtn = _mcf52xx_pcm_P5Q_rx(int_io_dev_ptr, send_buffer, 1, &recv_buffer[0], 3);
	data[0] = recv_buffer[0];
	data[1] = recv_buffer[1];
	data[2] = recv_buffer[2];

	printf("RDID: %02x %02x %02x \n", recv_buffer[0], recv_buffer[1], recv_buffer[2]);
	return rtn;
}


int_32 _mcf52xx_P5Q_spi_tx_cmd( IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar cmd_data);




/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  _mcf52xx_pcm_P5Q_cmd_wren
* Returned Value   :  int_32 error code
* Comments  :  
*
*END*---------------------------------------------------------------------*/

int_32  _mcf52xx_pcm_P5Q_cmd_wren(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr)
{
	uint_32	rtn = 0;

	rtn = _mcf52xx_P5Q_spi_tx_cmd(int_io_dev_ptr, FLASH_CMD_WREN);

	return rtn;
}


/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  _mcf52xx_pcm_P5Q_cmd_wrdi
* Returned Value   :  int_32 error code
* Comments  :  
*
*END*---------------------------------------------------------------------*/

int_32  _mcf52xx_pcm_P5Q_cmd_wrdi(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr)
{
	uint_32	rtn = 0;

	send_buffer[0] = FLASH_CMD_WRDI;
	rtn = _mcf52xx_pcm_P5Q_tx(int_io_dev_ptr, send_buffer, 1);

	return rtn;
}



/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  _mcf52xx_pcm_P5Q_cmd_rdsr
* Returned Value   :  int_32 error code
* Comments  :  
*
*END*---------------------------------------------------------------------*/

int_32  _mcf52xx_pcm_P5Q_cmd_rdsr(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar *status)
{
	uint_32	rtn = 0;

	rtn = _mcf52xx_P5Q_spi_rx_cmd(int_io_dev_ptr, FLASH_CMD_RDSR, status, 1);
	return rtn;
}


/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  _mcf52xx_pcm_P5Q_cmd_se
* Returned Value   :  int_32 error code
* Comments  :  
*
*END*---------------------------------------------------------------------*/
int_32  _mcf52xx_pcm_P5Q_cmd_se(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uint_32 addr)
{
	uint_32	i;
	uint_32	rtn = 0;
	static uchar status;

	rtn = _mcf52xx_pcm_P5Q_cmd_wren(int_io_dev_ptr);

	send_buffer[0] = FLASH_CMD_SE;
	send_buffer[3] = (addr)&0x00ff;
	send_buffer[2] = ((addr)>>8)&0x00ff;
	send_buffer[1] = ((addr)>>16)&0x00ff;
	_mcf52xx_pcm_P5Q_tx(int_io_dev_ptr, send_buffer, 4);

	return rtn;
}


/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  _mcf52xx_pcm_P5Q_cmd_se
* Returned Value   :  int_32 error code
* Comments  :  
*
*END*---------------------------------------------------------------------*/
int_32  _mcf52xx_pcm_P5Q_cmd_be(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr)
{
#if 0
	uint_32	i;
	uint_32	rtn = 0;
	static uchar status;
	rtn = _mcf52xx_pcm_P5Q_cmd_wren(int_io_dev_ptr);

	send_buffer[0] = 0xd8;
	send_buffer[3] = (addr)&0x00ff;
	send_buffer[2] = ((addr)>>8)&0x00ff;
	send_buffer[1] = ((addr)>>16)&0x00ff;
	_mcf52xx_pcm_P5Q_tx(int_io_dev_ptr, send_buffer, 4);
#endif

	uint_32	i;
	uint_32	rtn = 0;
	static uchar status;

	rtn = _mcf52xx_pcm_P5Q_cmd_rdsr(int_io_dev_ptr, &status);
	printf("RDSR: %02x\n", status);

	rtn = _mcf52xx_pcm_P5Q_cmd_wren(int_io_dev_ptr);

	send_buffer[0] = FLASH_CMD_BE;
	_mcf52xx_pcm_P5Q_tx(int_io_dev_ptr, send_buffer, 1);

	while(1){
		rtn = _mcf52xx_pcm_P5Q_cmd_rdsr(int_io_dev_ptr, &status);
		printf("RDSR: %02x\n", status);
		if ((status & 0x01) == 0){
			break;
		}
	}

	return rtn;
}


/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  _mcf52xx_pcm_P5Q_cmd_read
* Returned Value   :  int_32 error code
* Comments  :  
*
*END*---------------------------------------------------------------------*/

int_32  _mcf52xx_pcm_P5Q_cmd_read(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uint_32 addr, uchar *data, int_32 size)
{
	uint_32	i;
	uint_32	rtn = 0;
	uint_32	rx_size = 0;
	uint_32	rx_addr = 0;
	uint_32	total_size = 0;
	uchar   *rx_data;

	total_size = (uint_32)size;
	rx_addr = addr;
	rx_data = (uchar*)data;

	while(total_size>0){
		send_buffer[0] = FLASH_CMD_READ;
		send_buffer[3] = (uchar)(rx_addr);
		send_buffer[2] = (uchar)(rx_addr>>8);
		send_buffer[1] = (uchar)(rx_addr>>16);

		if (total_size >= ((DEFAULT_QSPI_RX_BUFFER_SIZE/2)-4)){
			rx_size = ((DEFAULT_QSPI_RX_BUFFER_SIZE/2)-4);
		}
		else{
			rx_size = total_size;
		}

		rtn = _mcf52xx_pcm_P5Q_rx(int_io_dev_ptr, send_buffer, 4, &recv_buffer[0], rx_size);

		rx_addr = rx_addr + rx_size;
		total_size = total_size - rx_size;

		i = 0;
		/* read received bytes from queue */
		while (rx_size > 0){
		   /* Store received data from QSPI_CSx into RX buffer */
			*rx_data++ = recv_buffer[i];
		    rx_size--;
			i++;
		}
	}

	return rtn;
}


/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  _mcf52xx_pcm_P5Q_cmd_pp_lp
* Returned Value   :  int_32 error code
* Comments  :  
*
*END*---------------------------------------------------------------------*/

int_32  _mcf52xx_pcm_P5Q_cmd_pp_lp(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uint_32 addr, uchar *data, int_32 size)
{
	uint_32	i;
	uint_32	rtn = 0;
	static uchar status;

	for (i=0;i<size;i++){

		rtn = _mcf52xx_pcm_P5Q_cmd_wren(int_io_dev_ptr);

		send_buffer[0] = 0x02;
		send_buffer[3] = (addr+i)&0x00ff;
		send_buffer[2] = ((addr+i)>>8)&0x00ff;
		send_buffer[1] = ((addr+i)>>16)&0x00ff;
		send_buffer[4] = data[i];
		_mcf52xx_pcm_P5Q_tx(int_io_dev_ptr, send_buffer, 5);

		while(1){
			rtn = _mcf52xx_pcm_P5Q_cmd_rdsr(int_io_dev_ptr, &status);
			if ((status & 0x01) != 0){
				break;
			}
		}
	}

	return rtn;
}

int_32 _mcf52xx_P5Q_spi_tx_data( IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar cmd_data, uint_32 addr, uchar_ptr buffer, int_32 size );


/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  _mcf52xx_pcm_P5Q_cmd_pp_baw
* Returned Value   :  int_32 error code
* Comments  :  
*
*END*---------------------------------------------------------------------*/

int_32  _mcf52xx_pcm_P5Q_cmd_pp_baw(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uint_32 addr, uchar *data, int_32 size)
{
	uint_32	i;
	uint_32	rtn = 0;
	uint_32	rx_size = 0;
	uint_32	rx_addr = 0;
	uint_32	total_size = 0;
	uchar   *rx_data;
	static uchar status;
	int_32	p5q_write_count;

	total_size = (uint_32)size;
	rx_addr = addr;
	rx_data = (uchar*)data;

	while(total_size>0){
#if 0
		if (total_size >= ((DEFAULT_QSPI_RX_BUFFER_SIZE/2)-8)){
			rx_size = ((DEFAULT_QSPI_RX_BUFFER_SIZE/2)-8);
		}
		else{
			rx_size = total_size;
		}
#else

		if (total_size > 64){
			rx_size = 64;
		}
		else{
			rx_size = total_size;
		}
#endif

		rtn = _mcf52xx_pcm_P5Q_cmd_wren(int_io_dev_ptr);

//		_mcf52xx_P5Q_spi_tx_data(int_io_dev_ptr, 0x22, rx_addr, rx_data, rx_size );
		_mcf52xx_P5Q_spi_tx_data(int_io_dev_ptr, FLASH_CMD_WRITE, rx_addr, rx_data, rx_size );

		rx_data = rx_data + rx_size;
		rx_addr = rx_addr + rx_size;
		total_size = total_size - rx_size;

		p5q_write_count = 0;
		while(1){
			p5q_write_count++;
			rtn = _mcf52xx_pcm_P5Q_cmd_rdsr(int_io_dev_ptr, &status);
			if ((status & 0x01) == 0){
				if (p5q_statistics.p5q_write_count_max < p5q_write_count){
					p5q_statistics.p5q_write_count_max = p5q_write_count;
				}
				break;
			}
		}
	}

	return rtn;
}



/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  _mcf52xx_pcm_P5Q_rx
* Returned Value   :  int_32 error code
* Comments  :  
*
*END*---------------------------------------------------------------------*/

int_32  _mcf52xx_pcm_P5Q_rx(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar *cmd_data, int_32 cmd_size, uchar *data, int_32 size)
{
	uint_32		num = 0;
	int i;
	static uchar pcm_recv_buffer[16];

   	/* Read data from EEPROM */
	for (i=0;i<cmd_size;i++){
		 pcm_recv_buffer[i] = cmd_data[i];
	}

	num = _mcf52xx_P5Q_spi_rx(int_io_dev_ptr, pcm_recv_buffer, (cmd_size + size));

	for (i=0;i<size;i++){
		 data[i] = pcm_recv_buffer[cmd_size + i];
	}

	return E_OK;
}



/*FUNCTION*-------------------------------------------------------------------
*
* Function Name    :  _mcf52xx_pcm_P5Q_tx
* Input Value      :
      [IN] The address of the device specific information : IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr,
      [IN] The array characters are to be read from       : uchar_ptr                        data,
      [IN] Number of char's to receive                    : int_32                           size
* Returned Value   :  int_32 error code
* Comments  :  
*
*END*---------------------------------------------------------------------*/

int_32  _mcf52xx_pcm_P5Q_tx(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar *data, int_32 size)
{
	uint_32		result;

	result = _mcf52xx_P5Q_spi_tx(int_io_dev_ptr, data, size);
	return E_OK;
}



/*FUNCTION****************************************************************
* 
* Function Name    : _mcf52xx_P5Q_spi_rx
* Input Value      :
      [IN] The address of the device specific information : IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr,
      [IN] The array characters are to be read from       : uchar_ptr                        buffer,
      [IN] Number of char's to receive                    : int_32                           size

* Returned Value   : Returns the number of bytes received or QSPI error   
* Comments         : 
*   Reads the data into provided array.
*
*END*********************************************************************/
int_32 _mcf52xx_P5Q_spi_rx(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar_ptr buffer, int_32 size)
{
	VMCF5XXX_QSPI_STRUCT_PTR        qspi_ptr;
	TIME_STRUCT                     time;
	uint_16_ptr                     buf_ptr = NULL;
	_mqx_int                        i, num, length = size;
	uint_32                         milliseconds;
	uint_16                         *pQDR;

	qspi_ptr = _bsp_get_qspi_base_address(0);

	pQDR = (uint_16*)&qspi_ptr->QDR;

	while (length > 0){
		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);

		if (length < DEFAULT_QSPI_RX_BUFFER_SIZE / 2){
			num = length;
		}
		else{
			num = DEFAULT_QSPI_RX_BUFFER_SIZE / 2;
		}

		/* Set up to "size" transfer buffer for CSx */
		for (i = 0; i < num; i++){
			//qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT | QSPI_QCR_DT;
			//qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT;
			*pQDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT;
		}

		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0000);
		for (i = 0; i < num; i++){
			//qspi_ptr->QDR = buffer[i];
			*pQDR = buffer[i];
		}

		/* Reset start queue pointer */
		qspi_ptr->QWR &= ~QSPI_QWR_NEWQP(0xF);
		/* Reset end queue pointer */
		qspi_ptr->QWR &= ~QSPI_QWR_ENDQP(0xF);
		/* Set end queue pointer */
		qspi_ptr->QWR |= QSPI_QWR_ENDQP(num - 1);

		/* Enable QSPI to start the transfer */
		qspi_ptr->QDLYR |= QSPI_QDLYR_SPE;

		/* Wait for transfer to complete */
		while ( ((qspi_ptr->QIR) & QSPI_QIR_SPIF) != QSPI_QIR_SPIF ) {
		}

		/* clear completion flag */
		qspi_ptr->QIR |= QSPI_QIR_SPIF;

		length -= num;

		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0010);

		/* read received bytes from queue */
		while (num > 0){
		   /* Store received data from QSPI_CSx into RX buffer */
			*buffer++ = (uchar)(qspi_ptr->QDR);
		    num--;
		}
	}

	return size;
}








/*FUNCTION****************************************************************
* 
* Function Name    : _mcf52xx_P5Q_spi_rx_cmd
* Returned Value   : Returns the number of bytes received or QSPI error   
* Comments         : 
*
*END*********************************************************************/
int_32 _mcf52xx_P5Q_spi_rx_cmd(IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar cmd_data, uchar_ptr buffer, int_32 size)
{
	VMCF5XXX_QSPI_STRUCT_PTR        qspi_ptr;
	TIME_STRUCT                     time;
	uint_16_ptr                     buf_ptr = NULL;
	_mqx_int                        i, num, length = (size+1);
	uint_32                         milliseconds;
	uint_16                         *pQDR;

	qspi_ptr = _bsp_get_qspi_base_address(0);

	pQDR = (uint_16*)&qspi_ptr->QDR;

	qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);

	num = length;

	/* Set up to "size" transfer buffer for CSx */
	for (i = 0; i < num; i++){
		*pQDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT;
	}

	qspi_ptr->QAR = QSPI_QAR_ADDR(0x0000);
	*pQDR = cmd_data;

	*pQDR = 0;

	/* Reset start queue pointer */
	qspi_ptr->QWR &= ~QSPI_QWR_NEWQP(0xF);
	/* Reset end queue pointer */
	qspi_ptr->QWR &= ~QSPI_QWR_ENDQP(0xF);
	/* Set end queue pointer */
	qspi_ptr->QWR |= QSPI_QWR_ENDQP(num - 1);

	/* Enable QSPI to start the transfer */
	qspi_ptr->QDLYR |= QSPI_QDLYR_SPE;
	/* Wait for transfer to complete */

	/* Wait for transfer to complete */
	while ( ((qspi_ptr->QIR) & QSPI_QIR_SPIF) != QSPI_QIR_SPIF ) {
	}

	/* clear completion flag */
	qspi_ptr->QIR |= QSPI_QIR_SPIF;

	qspi_ptr->QAR = QSPI_QAR_ADDR(0x0011);

	/* read received bytes from queue */
	*buffer = (uchar)(qspi_ptr->QDR);

	return size;
}


/*FUNCTION****************************************************************
* 
* Function Name    : _mcf52xx_P5Q_spi_tx
* Input Value      :
      [IN] The address of the device specific information : IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr,
      [IN] The array characters are to be read from       : uchar_ptr                        buffer,
      [IN] Number of char's to transmit                   : int_32                           size

* Returned Value   : return number of byte transmitted or QSPI error code
* Comments         : 
*   Writes the provided data buffer and loops until transmission complete
*
*END*********************************************************************/
int_32 _mcf52xx_P5Q_spi_tx( IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar_ptr buffer, int_32 size )
{
   VMCF5XXX_QSPI_STRUCT_PTR        qspi_ptr;
   TIME_STRUCT                     time;
   boolean                         flag = FALSE;
   _mqx_int                        num, i, length = size;
   uint_32                         milliseconds;
   volatile uint_16                buf_ptr = 0;

   qspi_ptr = _bsp_get_qspi_base_address(0);

   /* Clear halt bit */
	if (qspi_ptr->QWR & QSPI_QWR_HALT){
		qspi_ptr->QWR &= ~QSPI_QWR_HALT;
	}

   /* Clear SPIF bit */
	if (qspi_ptr->QIR & QSPI_QIR_SPIF){
		qspi_ptr->QIR |= (QSPI_QIR_SPIF);
	}

	/* Set queue pointer to the first command RAM entry */
	qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);
	/* use default delay */

	if (qspi_ptr->QDR & QSPI_QCR_DT){
		qspi_ptr->QDR &= QSPI_QDR_COMMAND(~QSPI_QCR_DT);
	}

	if (qspi_ptr->QDR & QSPI_QCR_DSCK){
		qspi_ptr->QDR &= QSPI_QDR_COMMAND(~QSPI_QCR_DSCK);
	}

	/* Disable wrap around */
	qspi_ptr->QWR &= ~QSPI_QWR_WREN;

	/* Reset start queue pointer */
	qspi_ptr->QWR &= ~QSPI_QWR_NEWQP(0xF);

	while (length > 0) {
		/* Reset end queue pointer */
		qspi_ptr->QWR &= ~QSPI_QWR_ENDQP(0xF);

		if ( length >= (DEFAULT_QSPI_TX_BUFFER_SIZE / 2) ) {
			/* Set queue end pointer at entry DEFAULT_QSPI_TX_BUFFER_SIZE / 2 */
			qspi_ptr->QWR |= QSPI_QWR_ENDQP( DEFAULT_QSPI_TX_BUFFER_SIZE / 2 - 1 );
			num = DEFAULT_QSPI_TX_BUFFER_SIZE / 2;
			flag = FALSE;
		}
		else {
			/* Set queue end pointer at entry less than 16 */
			/* Begin CR2101 */
			qspi_ptr->QWR |= QSPI_QWR_ENDQP(size - 1);
			num = length;
			/* End CR2101 */
			flag = TRUE;
		}

		/* Set queue pointer to the first command RAM entry */
		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);

		/* Set up transfer buffer for CSx */
		for (i = 0; i < num; i++){
			//qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT | QSPI_QCR_DT;
			qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT;
		}

		/* Set queue pointer to the first transmit RAM entry */
		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0000);

		for (i = 0; i < num; i++){
			qspi_ptr->QDR = (uint_16)buffer[i];
		} 

      	length -= num;

      	/* Enable QSPI to start the transfer */
      	qspi_ptr->QDLYR |= QSPI_QDLYR_SPE;

      	while ( ((qspi_ptr->QIR) & QSPI_QIR_SPIF) != QSPI_QIR_SPIF ) {
      	}

      	qspi_ptr->QIR |= QSPI_QIR_SPIF;

	}

	return size;
}



/*FUNCTION****************************************************************
* 
* Function Name    : _mcf52xx_P5Q_spi_tx_cmd
* Returned Value   : return number of byte transmitted or QSPI error code
* Comments         : 
*   Writes the provided data buffer and loops until transmission complete
*
*END*********************************************************************/
int_32 _mcf52xx_P5Q_spi_tx_cmd( IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar cmd_data)
{
   VMCF5XXX_QSPI_STRUCT_PTR        qspi_ptr;
   TIME_STRUCT                     time;
   boolean                         flag = FALSE;
   _mqx_int                        num, i, length = 1;
   uint_32                         milliseconds;
   volatile uint_16                buf_ptr = 0;

   qspi_ptr = _bsp_get_qspi_base_address(0);

   /* Clear halt bit */
	if (qspi_ptr->QWR & QSPI_QWR_HALT){
		qspi_ptr->QWR &= ~QSPI_QWR_HALT;
	}

   /* Clear SPIF bit */
	if (qspi_ptr->QIR & QSPI_QIR_SPIF){
		qspi_ptr->QIR |= (QSPI_QIR_SPIF);
	}

	/* Set queue pointer to the first command RAM entry */
	qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);

	if (qspi_ptr->QDR & QSPI_QCR_DT){
		qspi_ptr->QDR &= QSPI_QDR_COMMAND(~QSPI_QCR_DT);
	}

	if (qspi_ptr->QDR & QSPI_QCR_DSCK){
		qspi_ptr->QDR &= QSPI_QDR_COMMAND(~QSPI_QCR_DSCK);
	}

	/* Disable wrap around */
	qspi_ptr->QWR &= ~QSPI_QWR_WREN;

	/* Reset start queue pointer */
	qspi_ptr->QWR &= ~QSPI_QWR_NEWQP(0xF);

	/* Reset end queue pointer */
	qspi_ptr->QWR &= ~QSPI_QWR_ENDQP(0xF);

	/* Set queue end pointer at entry less than 16 */
	qspi_ptr->QWR |= QSPI_QWR_ENDQP((length) - 1);
	num = length;

	/* Set queue pointer to the first command RAM entry */
	qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);

	/* Set up transfer buffer for CSx */
	for (i = 0; i < num; i++){
		//qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT | QSPI_QCR_DT;
		qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT;
	}

	/* Set queue pointer to the first transmit RAM entry */
	qspi_ptr->QAR = QSPI_QAR_ADDR(0x0000);

	qspi_ptr->QDR = cmd_data;

	/* Enable QSPI to start the transfer */
	qspi_ptr->QDLYR |= QSPI_QDLYR_SPE;

	while ( ((qspi_ptr->QIR) & QSPI_QIR_SPIF) != QSPI_QIR_SPIF ) {
	}

	qspi_ptr->QIR |= QSPI_QIR_SPIF;

	return 1;
}


/* 特殊処理を行うことで 処理速度の最適化をしています。※ただし QSPIの処理参考までに 古い処理を残しておきます。 */
#if 1


/*FUNCTION****************************************************************
* 
* Function Name    : _mcf52xx_P5Q_spi_tx_data
* Returned Value   : return number of byte transmitted or QSPI error code
* Comments         : 
*   Writes the provided data buffer and loops until transmission complete
*
*END*********************************************************************/
int_32 _mcf52xx_P5Q_spi_tx_data( IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar cmd_data, uint_32 addr, uchar_ptr buffer, int_32 size )
{
	VMCF5XXX_QSPI_STRUCT_PTR        qspi_ptr;
	boolean                         flag = FALSE;
	_mqx_int                        num, i, length = size+4;
	uint_32                         frame_count;
	uint_32                         data_count;

	qspi_ptr = _bsp_get_qspi_base_address(0);

	if (size > 8){
	   /* Clear halt bit */
		if (qspi_ptr->QWR & QSPI_QWR_HALT){
			qspi_ptr->QWR &= ~QSPI_QWR_HALT;
		}

	   /* Clear SPIF bit */
		if (qspi_ptr->QIR & QSPI_QIR_SPIF){
			qspi_ptr->QIR |= (QSPI_QIR_SPIF);
		}

		/* Set queue pointer to the first command RAM entry */
		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);
		/* use default delay */

		if (qspi_ptr->QDR & QSPI_QCR_DT){
			qspi_ptr->QDR &= QSPI_QDR_COMMAND(~QSPI_QCR_DT);
		}

		if (qspi_ptr->QDR & QSPI_QCR_DSCK){
			qspi_ptr->QDR &= QSPI_QDR_COMMAND(~QSPI_QCR_DSCK);
		}

		/* Disable wrap around */
		qspi_ptr->QWR &= ~QSPI_QWR_WREN;

		/* Reset start queue pointer */
		qspi_ptr->QWR &= ~QSPI_QWR_NEWQP(0xF);

		frame_count = 0;
		data_count = 0;

		BSP_QSPI_CS0_Low();

		while (length > 0) {

			/* Reset end queue pointer */
			qspi_ptr->QWR &= ~QSPI_QWR_ENDQP(0xF);

			if ( length > (DEFAULT_QSPI_TX_BUFFER_SIZE / 2) ) {
				/* Set queue end pointer at entry DEFAULT_QSPI_TX_BUFFER_SIZE / 2 */
				qspi_ptr->QWR |= QSPI_QWR_ENDQP( DEFAULT_QSPI_TX_BUFFER_SIZE / 2 - 1 );
				num = DEFAULT_QSPI_TX_BUFFER_SIZE / 2;
				flag = FALSE;
			}
			else {
				/* Set queue end pointer at entry less than 16 */
				/* Begin CR2101 */
				qspi_ptr->QWR |= QSPI_QWR_ENDQP(length - 1);
				num = length;
				/* End CR2101 */
				flag = TRUE;
			}

			/* Set queue pointer to the first command RAM entry */
			qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);

			/* Set up transfer buffer for CSx */
			for (i = 0; i < num; i++){
				//qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT | QSPI_QCR_DT;
				qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT;
			}

			/* Set queue pointer to the first transmit RAM entry */
			qspi_ptr->QAR = QSPI_QAR_ADDR(0x0000);

			if (frame_count==0){
				qspi_ptr->QDR = (uchar)cmd_data;
				qspi_ptr->QDR = (uchar)(addr>>16);
				qspi_ptr->QDR = (uchar)(addr>>8);
				qspi_ptr->QDR = (uchar)addr;

				for (i = 0; i < (num-4); i++){
					qspi_ptr->QDR = (uint_16)buffer[data_count];
					data_count++;
				} 
			}
			else{
				for (i = 0; i < num; i++){
					qspi_ptr->QDR = (uint_16)buffer[data_count];
					data_count++;
				} 
			}

			length -= num;

			/* Enable QSPI to start the transfer */
			qspi_ptr->QDLYR |= QSPI_QDLYR_SPE;

			while ( ((qspi_ptr->QIR) & QSPI_QIR_SPIF) != QSPI_QIR_SPIF ) {
			}

			qspi_ptr->QIR |= QSPI_QIR_SPIF;

			frame_count++;
		}

		BSP_QSPI_CS0_Hi();
	}
	else{

	   /* Clear halt bit */
		if (qspi_ptr->QWR & QSPI_QWR_HALT){
			qspi_ptr->QWR &= ~QSPI_QWR_HALT;
		}

	   /* Clear SPIF bit */
		if (qspi_ptr->QIR & QSPI_QIR_SPIF){
			qspi_ptr->QIR |= (QSPI_QIR_SPIF);
		}

		/* Set queue pointer to the first command RAM entry */
		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);
		/* use default delay */

		if (qspi_ptr->QDR & QSPI_QCR_DT){
			qspi_ptr->QDR &= QSPI_QDR_COMMAND(~QSPI_QCR_DT);
		}

		if (qspi_ptr->QDR & QSPI_QCR_DSCK){
			qspi_ptr->QDR &= QSPI_QDR_COMMAND(~QSPI_QCR_DSCK);
		}

		/* Disable wrap around */
		qspi_ptr->QWR &= ~QSPI_QWR_WREN;

		/* Reset start queue pointer */
		qspi_ptr->QWR &= ~QSPI_QWR_NEWQP(0xF);

		/* Reset end queue pointer */
		qspi_ptr->QWR &= ~QSPI_QWR_ENDQP(0xF);

		/* Set queue end pointer at entry less than 16 */
		qspi_ptr->QWR |= QSPI_QWR_ENDQP(length - 1);
		num = length;

		/* Set queue pointer to the first command RAM entry */
		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);

		/* Set up transfer buffer for CSx */
		for (i = 0; i < num; i++){
			//qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT | QSPI_QCR_DT;
			qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT;
		}

		/* Set queue pointer to the first transmit RAM entry */
		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0000);

		qspi_ptr->QDR = (uchar)cmd_data;
		qspi_ptr->QDR = (uchar)(addr>>16);
		qspi_ptr->QDR = (uchar)(addr>>8);
		qspi_ptr->QDR = (uchar)addr;

		for (i = 0; i < size; i++){
			qspi_ptr->QDR = (uint_16)buffer[i];
		} 

		/* Enable QSPI to start the transfer */
		qspi_ptr->QDLYR |= QSPI_QDLYR_SPE;

		while ( ((qspi_ptr->QIR) & QSPI_QIR_SPIF) != QSPI_QIR_SPIF ) {
		}

		qspi_ptr->QIR |= QSPI_QIR_SPIF;
	}

	return size;
}


#else

/*FUNCTION****************************************************************
* 
* Function Name    : _mcf52xx_P5Q_spi_tx_data
* Returned Value   : return number of byte transmitted or QSPI error code
* Comments         : 
*   Writes the provided data buffer and loops until transmission complete
*
*END*********************************************************************/

int_32 _mcf52xx_P5Q_spi_tx_data( IO_P5Q_SPI_DEVICE_STRUCT_PTR int_io_dev_ptr, uchar cmd_data, uint_32 addr, uchar_ptr buffer, int_32 size )
{
   VMCF52XX_QSPI_STRUCT_PTR        qspi_ptr;
   TIME_STRUCT                     time;
   boolean                         flag = FALSE;
   _mqx_int                        num, i, length = size+4;
   uint_32                         milliseconds;
   volatile uint_16                buf_ptr = 0;
	uint_32                        frame_count;
	uint_32                        data_count;

   qspi_ptr = _bsp_get_qspi_base_address(0);


	   /* Clear halt bit */
		if (qspi_ptr->QWR & QSPI_QWR_HALT){
			qspi_ptr->QWR &= ~QSPI_QWR_HALT;
		}

	   /* Clear SPIF bit */
		if (qspi_ptr->QIR & QSPI_QIR_SPIF){
			qspi_ptr->QIR |= (QSPI_QIR_SPIF);
		}

		/* Set queue pointer to the first command RAM entry */
		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);
		/* use default delay */

		if (qspi_ptr->QDR & QSPI_QCR_DT){
			qspi_ptr->QDR &= QSPI_QDR_COMMAND(~QSPI_QCR_DT);
		}

		if (qspi_ptr->QDR & QSPI_QCR_DSCK){
			qspi_ptr->QDR &= QSPI_QDR_COMMAND(~QSPI_QCR_DSCK);
		}

		/* Disable wrap around */
		qspi_ptr->QWR &= ~QSPI_QWR_WREN;

		/* Reset start queue pointer */
		qspi_ptr->QWR &= ~QSPI_QWR_NEWQP(0xF);

		/* Reset end queue pointer */
		qspi_ptr->QWR &= ~QSPI_QWR_ENDQP(0xF);

		/* Set queue end pointer at entry less than 16 */
		qspi_ptr->QWR |= QSPI_QWR_ENDQP(length - 1);
		num = length;

		/* Set queue pointer to the first command RAM entry */
		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0020);

		/* Set up transfer buffer for CSx */
		for (i = 0; i < num; i++){
			//qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT | QSPI_QCR_DT;
			qspi_ptr->QDR = QSPI_QCR_CS(QSPI_CHIP_SELECT1) | QSPI_QCR_BITSE | QSPI_QCR_CONT;
		}

		/* Set queue pointer to the first transmit RAM entry */
		qspi_ptr->QAR = QSPI_QAR_ADDR(0x0000);

		qspi_ptr->QDR = (uchar)cmd_data;
		qspi_ptr->QDR = (uchar)(addr>>16);
		qspi_ptr->QDR = (uchar)(addr>>8);
		qspi_ptr->QDR = (uchar)addr;

		for (i = 0; i < size; i++){
			qspi_ptr->QDR = (uint_16)buffer[i];
		} 

		/* Enable QSPI to start the transfer */
		qspi_ptr->QDLYR |= QSPI_QDLYR_SPE;

		while ( ((qspi_ptr->QIR) & QSPI_QIR_SPIF) != QSPI_QIR_SPIF ) {
		}

		qspi_ptr->QIR |= QSPI_QIR_SPIF;

	return size;
}
#endif

/* EOF */