/*
 * mmcsdSample_io.c
 *
 * This sample application, is a representative test program. This application
 * tests MMCSD driver on Bios 6.
 *
 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
 *
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *    Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 *    Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the
 *    distribution.
 *
 *    Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

/** \file   mmcsdSample_io.c
 *
 *  \brief  Demo fatfs application for the MMCSD driver
 *
 *  This sample application, is a representative test program.
 *  This application test MMCSD driver on Bios.
 *
 *  (C) Copyright 2010, Texas Instruments, Inc
 *
 */

#include <xdc/std.h>
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/io/iom.h>
#include <ti/sysbios/knl/Semaphore.h>
#include "ti/sysbios/knl/task.h"
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>
#include <xdc/runtime/Log.h>
#include <xdc/runtime/Timestamp.h>
#include <xdc/runtime/Types.h>

#include <string.h>
#include <file.h>
#include <stdio.h>
#include <stdlib.h>

#include "platforms/evm6748/Mmcsd_evmInit.h"

#include "mmcsd/include/psp_mmcsd.h"
#include "blkmedia/include/psp_blkdev.h"

#include "ti/sysbios/fatfs/ff.h"
#include "ti/sysbios/fatfs/diskio.h"

#define PSP_MMCSD_SAMPLE_DRIVE            1U
/* This is the driver number associated with MMCSD drive                       */
#define MMC_INST_ID                     0U
/*Instance no of mmcsd                                                        */

/*#define NUM_SECTORS                     6144U*/
#define NUM_SECTORS                     6144U
/*No of Bytes in drive to format                                              */
#define FILESYS_BYTE_COUNT                      (NUM_SECTORS * 512U)

/*No of sectors read or written                                               */
//Titus
//#define WRITE_SECTORS                 500
#define WRITE_SECTORS                 2048
/* No of bytes to write or read                                               */
#define BYTE_COUNT                      (WRITE_SECTORS * 512U)

#define INCLUDE_MEDIA_WP_TEST           0
/*This will enable the WP test on the media.                                  */

#define INCLUDE_ACTUAL_CARD_FREQ_IOCTL  0
/*This will actually alter the freq of the card.
 Please note that the further operation of the card takes place at this freq*/

#define BUFFER_ALINED_CACHE_LENGTH
/* Enable this if user want to pass cache length aligned buffer, In polled mode
 buffer must be 4 byte aligned */

#define DATA_ALIGN                      128

#define MMCSD_SAMPLE_PRINT printf

char *filename = "fat:1:sample.txt";
TCHAR *path = "fat:1:sample.txt";
#define READ_BLOCK_SIZE 64

/*
 * Global Static references
 */
UInt32 sectorCount = WRITE_SECTORS;
Ptr handle;
PSP_BlkDevOps_t* pDevOps = NULL;
/*
 * Note: Buffer alignment is required only when working in DMA Mode.
 */
static UInt8 srcmmcsdBufOrg[BYTE_COUNT + DATA_ALIGN];
/*+128 if need to make unalign for testing purpose*/
static UInt8 dstmmcsdBufOrg[BYTE_COUNT + DATA_ALIGN];
/*+128 if need to make unalign for testing purpose*/
static UInt8 *srcmmcsdBuf = NULL;
static UInt8 *dstmmcsdBuf = NULL;
UInt32 loop = 0;
UInt32 addr = 0;

Void checkMediaCard(UInt32 instanceId);

Void checkMediaCard(UInt32 instanceId)
{
    Int32 result = IOM_COMPLETED, flag = 1;
    PSP_MmcsdCardType cardType = PSP_MMCSD_CARDTYPE_NONE;

    while (flag)
    {
        result = PSP_mmcsdCheckCard(&cardType, instanceId);
        if (IOM_COMPLETED == result)
        {
            if ((PSP_MMCSD_CARDTYPE_MMC == cardType)
                    || (PSP_MMCSD_CARDTYPE_SD == cardType))
            {
                break;
            }
            else
            {
                MMCSD_SAMPLE_PRINT(" MMCSD_SAMPLE: Please insert the card\r\n");
                Task_sleep(1000U);
            }
        }
        else
        {
            MMCSD_SAMPLE_PRINT(" MMCSD_SAMPLE: checkCard failed\r\n");
        }
    }
}

/**
 *  \brief Demonstrates use of PSP drivers.
 */
Void runMmcsdSample()
{
    UInt8 *tempSrcMmcsdBuf = NULL;
    UInt8 *tempDstMmcsdBuf = NULL;
    Int32 retVal = IOM_COMPLETED;
    FILE *pFile;
    UInt32 readSize = 0, writeSize = 0;
    UInt32 cnt = 0, i = 0, loopCnt = 5;
    //FIL fileptr;
    //FRESULT result;
    //BYTE mode = 0;
    UInt ts1, ts2;
    Types_FreqHz  freq;



    /* aligning srcmmcsdBuf & dstmmcsdBuf on CACHE line size boundary */
    memset(srcmmcsdBufOrg, 0xFF, sizeof(srcmmcsdBufOrg));
    memset(dstmmcsdBufOrg, 0xFF, sizeof(dstmmcsdBufOrg));

    tempSrcMmcsdBuf = srcmmcsdBufOrg;
    tempDstMmcsdBuf = dstmmcsdBufOrg;

    /* Align the buffer on the cache line length */
    srcmmcsdBuf = (Ptr) ((UInt32) (tempSrcMmcsdBuf + DATA_ALIGN - 1)
            & ~(DATA_ALIGN - 1));
    dstmmcsdBuf = (Ptr) ((UInt32) (tempDstMmcsdBuf + DATA_ALIGN - 1)
            & ~(DATA_ALIGN - 1));
    if ((NULL == srcmmcsdBuf) || (NULL == dstmmcsdBuf))
    {
        MMCSD_SAMPLE_PRINT(" MMCSD_SAMPLE:Buffer is NULL\r\n");
    }

    checkMediaCard(MMC_INST_ID);
    MMCSD_SAMPLE_PRINT(" MMCSD_SAMPLE:Card is inserted\r\n");

#ifndef BUFFER_ALINED_CACHE_LENGTH
    srcmmcsdBuf += 4;
    dstmmcsdBuf += 4;
#endif /* BUFFER_ALINED_CACHE_LENGTH */

    retVal = PSP_blkmediaFATfsRegister(MMC_INST_ID, PSP_MMCSD_SAMPLE_DRIVE);
    if (IOM_COMPLETED == retVal)
    {
        MMCSD_SAMPLE_PRINT(
                " MMCSD_SAMPLE: Media is registered with FATfs \r\n");
    }
    else
    {
        MMCSD_SAMPLE_PRINT(
                " MMCSD_SAMPLE: Media is registering with FATfs FAILED\r\n");
        return;
    }

    cnt = sectorCount * 512U;

    for (i = 0; i < cnt; i++)
    {
        srcmmcsdBuf[i] = i;
        dstmmcsdBuf[i] = 0;
    }
#if 1
    MMCSD_SAMPLE_PRINT("MMCSD_SAMPLE: Create Fat format on MMCSD\n");
    /* Format the Nand drive */
    retVal = f_mkfs(PSP_MMCSD_SAMPLE_DRIVE, 1, FILESYS_BYTE_COUNT);
    if (retVal == 0)
    {
        MMCSD_SAMPLE_PRINT("MMCSD_SAMPLE: create partition successful\n");
    }
    else
    {
        MMCSD_SAMPLE_PRINT(
                "MMCSD_SAMPLE: partition creation failed errno: %d\n", retVal);
    }
#endif
    /* open the mmcsd file for reading */
    pFile = fopen(filename, "w+");


    if (NULL == pFile)
    {
        MMCSD_SAMPLE_PRINT("ERROR: FatFs fxn 'fopen' returned NULL.\n");
        return;
    }

//setvbuf(pFile,NULL,_IOFBF,512);

    MMCSD_SAMPLE_PRINT("Writing into MMC/SD via \"fwrite\" \n");


    Timestamp_getFreq(&freq);
    ts1 = Timestamp_get32();
    writeSize = fwrite(srcmmcsdBuf, 1, cnt, pFile);
//        writeSize = fwrite(srcmmcsdBuf, 512, 500, pFile);
    ts2 = Timestamp_get32();

    System_printf("T1: %u\n"
                  "T2: %u\n"
                  "dT: %u\n"
                  "dT(us): %u\n"
                  "Freq: %u\n",
                  ts1,
                  ts2,
                  ts2-ts1,
                  (ts2-ts1) / (freq.lo / 1000000), //delta t in us
                  freq.lo);






    if (cnt != writeSize)
    {
        MMCSD_SAMPLE_PRINT(
                "ERROR: FatFs fxn 'fwrite' returned write size %d.\n",
                writeSize);
        return;
    }

    /* seek the file pointer to begining location */
    if ((fflush(pFile)) != 0)
    {
        MMCSD_SAMPLE_PRINT("ERROR: FatFs fxn 'fflush' returned error.\n");
        return;
    }


//    while (loop < loopCnt)
//    {
//        /* write contents of the file into a buffer */
//        writeSize = fwrite(srcmmcsdBuf, 1, cnt, pFile);
//        if (cnt != writeSize)
//        {
//            MMCSD_SAMPLE_PRINT(
//                    "ERROR: FatFs fxn 'fwrite' returned write size %d.\n",
//                    writeSize);
//            break;
//        }
//
//        /* seek the file pointer to begining location */
//        if ((fflush(pFile)) != 0)
//        {
//            MMCSD_SAMPLE_PRINT("ERROR: FatFs fxn 'fflush' returned error.\n");
//            break;
//        }
//
//        /* seek the file pointer to begining location */
//        if ((fseek(pFile, 0, SEEK_SET)) != 0)
//        {
//            MMCSD_SAMPLE_PRINT("ERROR: FatFs fxn 'fseek' returned error.\n");
//            break;
//        }
//
//        /* read contents of the file into a buffer */
//        readSize = fread(dstmmcsdBuf, 1, cnt, pFile);
//        if (cnt != readSize)
//        {
//            MMCSD_SAMPLE_PRINT(
//                    "ERROR: FatFs fxn 'fread' returned read size %d.\n",
//                    readSize);
//            break;
//        }
//
//        /* seek the file pointer to begining location */
//        if ((fseek(pFile, 0, SEEK_SET)) != 0)
//        {
//            MMCSD_SAMPLE_PRINT("ERROR: FatFs fxn 'fseek' returned error.\n");
//            break;
//        }
//
//        for (i = 0; i < cnt; i++)
//        {
//            if (srcmmcsdBuf[i] != dstmmcsdBuf[i])
//            {
//                break;
//            }
//        }
//        if (i == cnt)
//        {
//            MMCSD_SAMPLE_PRINT(" MMCSD_SAMPLE: FILE Data write-read"
//                    " matching passed\r\n");
//        }
//        else
//        {
//            MMCSD_SAMPLE_PRINT(" MMCSD_SAMPLE: FILE Data write-read matching"
//                    " failed in loop count %d at i = %d\r\n", loop, i);
//        }
//        loop++;
//    }
    if ((fclose(pFile)) != 0)
    {
        MMCSD_SAMPLE_PRINT("ERROR: FatFs fxn 'fclose' returned error.\n");
    }

    /*The Media Driver clients like Mass Storage drivers shall use this
     function to un-register from a Block media device*/
    retVal = PSP_blkmediaFATfsUnregister(PSP_MMCSD_SAMPLE_DRIVE);
    if (IOM_COMPLETED == retVal)
    {
        MMCSD_SAMPLE_PRINT(" MMCSD_SAMPLE: Media for remote client is"
                " unregsitered\r\n");
    }
    else
    {
        MMCSD_SAMPLE_PRINT(" MMCSD_SAMPLE: Media for remote client is"
                " not unregsitered\r\n");
    }
}

/* ========================================================================== */
/*                              END OF FILE                                   */
/* ========================================================================== */

