/**
 * @file        sdram_diskio.c
 *
 * @brief       SDRAM Disk I/O driver
 *
 * @attention
 *
 *  Copyright (C) 2024 Geehy Semiconductor
 *
 *  You may not use this file except in compliance with the
 *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
 *
 *  The program is only for reference, which is distributed in the hope
 *  that it will be useful and instructional for customers to develop
 *  their software. Unless required by applicable law or agreed to in
 *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
 *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
 *  and limitations under the License.
 */

#include "ffconf.h"

#ifdef FF_SDRAM_DISK_ENABLE

/* Includes ***************************************************************/
#include "sdram_diskio.h"

/* Private includes *******************************************************/
#include <string.h>
#include "apm32f4xx_device_cfg.h"
#include "board_sdram.h"

/* Private macro **********************************************************/
#define SDRAM_BLOCK_SIZE     512U

/* Private typedef ********************************************************/

/* Private variables ******************************************************/

/* Private function prototypes ********************************************/

/* External variables *****************************************************/

/* External functions *****************************************************/

/**
 * @brief  Get Drive Status
 * 
 * @param  lun: Logical unit number
 * 
 * @retval DSTATUS: Drive status
 */
DSTATUS SDRAM_GetDiskStatus(BYTE lun)
{
    DSTATUS stat = STA_NOINIT;

    return stat;
}

/**
 * @brief  Initialize Disk Drive
 * 
 * @param  lun: Logical unit number
 * 
 * @retval DSTATUS: Drive status
 */
DSTATUS SDRAM_DiskInitialize(BYTE lun)
{
    DSTATUS stat = STA_NOINIT;

    BOARD_SDRAM_Init();

    return stat;
}

/**
 * @brief  Read Sector(s)
 * 
 * @param  lun: Logical unit number
 * 
 * @param  buff: Data buffer to store read data
 * 
 * @param  sector: Sector number to read
 * 
 * @param  count: Number of sectors to read
 * 
 * @retval DRESULT: Operation result
 */
DRESULT SDRAM_DiskRead(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
    memcpy(buff, (uint32_t *)(SDRAM_DEVICE_ADDR + (sector * SDRAM_BLOCK_SIZE)), (SDRAM_BLOCK_SIZE * count) / 4U);

    return RES_OK;
}

/**
 * @brief  Write Sector(s)
 * 
 * @param  lun: Logical unit number
 * 
 * @param  buff: Data buffer to write
 * 
 * @param  sector: Sector number to write
 * 
 * @param  count: Number of sectors to write
 * 
 * @retval DRESULT: Operation result
 */
DRESULT SDRAM_DiskWrite(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
    memcpy((uint32_t *)(SDRAM_DEVICE_ADDR + (sector * SDRAM_BLOCK_SIZE)), buff, (SDRAM_BLOCK_SIZE * count) / 4U);

    return RES_OK;
}

/**
 * @brief  I/O Control
 * 
 * @param  lun: Logical unit number
 * 
 * @param  cmd: Control command code
 * 
 * @param  buff: Data buffer
 * 
 * @retval DRESULT: Operation result
 */
DRESULT SDRAM_DiskIoctl(BYTE lun, BYTE cmd, void *buff)
{
    DRESULT res = RES_PARERR;

    switch (cmd)
    {
        case CTRL_SYNC:
            res = RES_OK;
            break;

        case GET_SECTOR_COUNT:
            *(DWORD*)buff = SDRAM_DEVICE_SIZE / SDRAM_BLOCK_SIZE;
            res = RES_OK;
            break;

        case GET_SECTOR_SIZE:
            *(DWORD*)buff = SDRAM_BLOCK_SIZE;
            res = RES_OK;
            break;

        case GET_BLOCK_SIZE:
            *(DWORD*)buff = 1;
            res = RES_OK;
            break;

        default:
            res = RES_PARERR;
            break;
    }

    return res;
}

#endif /* FF_SDRAM_DISK_ENABLE */
