/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * 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 the copyright holder 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
 * HOLDER 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.
 *
 *****************************************************************************/

#ifndef BLKMGR_IF_H
#define BLKMGR_IF_H


//-----------------------------------------------------------------------------
// Include files
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Configurations
//-----------------------------------------------------------------------------


//-----------------------------------------------------------------------------
// Constant definitions
//-----------------------------------------------------------------------------
/// Define Error code
#define BLKMGR_E_OK             (INT32)(0)          ///< Success
#define BLKMGR_E_FAIL           (INT32)(-1)         ///< IO error
#define BLKMGR_E_INVALID_PARAM  (INT32)(-2)         ///< Get the invalid param
#define BLKMGR_E_MEMORY_ALLOC   (INT32)(-3)         ///< Memory allocation fail


//-----------------------------------------------------------------------------
// Type definitions
//-----------------------------------------------------------------------------

/// define is base on BLKDEV_STATUS_T in x_blk_dev.h.
typedef enum
{
    BLOCK_DEV_DISCONNECT = 0,       ///< Device is offline
    BLOCK_DEV_FAIL,                 ///< Device is online but can not work
    BLOCK_DEV_CONNECT               ///< Device is online and work fine
} BLOCK_DEV_STATE;

/// Callbalck function when the device/medium is inserted or removed
typedef VOID  (*BLOCK_CALLBACK)(UINT32 u4Tag, INT32 i4Status);

/// Definition of functions in the IO function table
typedef INT32 (*BLOCK_GETTOTALLUN)(VOID);
typedef INT32 (*BLOCK_GETLUN)(VOID);
typedef INT32 (*BLOCK_SETLUN)(UINT32 u4Lun);
typedef INT64 (*BLOCK_GETSIZE)(VOID);
typedef INT32 (*BLOCK_GETBLOCKSIZE)(VOID);
typedef INT32 (*BLOCK_GETSTATUS)(VOID);
typedef CHAR* (*BLOCK_GETMODEL)(VOID);
typedef INT32 (*BLOCK_ERASE)(UINT64 u8Offset, UINT32 u4ByteCount);
typedef INT32 (*BLOCK_READ)(UINT64 u8Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
typedef INT32 (*BLOCK_WRITE)(UINT64 u8Offset, UINT32 u4MemPtr, UINT32 u4MemLen);
typedef VOID  (*BLOCK_SetHotswapCallback)(UINT32 u4Tag, BLOCK_CALLBACK pfnCallback);

/// IO function table exported by each block device
typedef struct _BlockIOFunc 
{
    BLOCK_GETTOTALLUN           pfnGetTotalLun;     ///< Get total lun
    BLOCK_GETLUN                pfnGetLun;          ///< Get the current lun
    BLOCK_SETLUN                pfnSetLun;          ///< Set the specific lun
    BLOCK_GETSIZE               pfnGetSize;         ///< Get the device size
    BLOCK_GETBLOCKSIZE          pfnGetBlockSize;    ///< Get the block size
    BLOCK_GETSTATUS             pfnGetStatus;       ///< Get the device status
    BLOCK_GETMODEL              pfnGetModel;        ///< Get the model name
    BLOCK_ERASE                 pfnErase;           ///< Erase device
    BLOCK_READ                  pfnRead;            ///< Read device
    BLOCK_WRITE                 pfnWrite;           ///< Write deivce
    BLOCK_SetHotswapCallback    pfnSetNotify;       ///< Set the notify function
} BlockFunc_T;

/// Query the IO function table of the block device
typedef INT32 (*BLOCK_GETFUNC)(BlockFunc_T *pFuncTable);

/// The type of the block devices
typedef enum
{
    BLOCK_DEV_USB = 0,              ///< USB device
    BLOCK_DEV_MS,                   ///< MS card
    BLOCK_DEV_SD,                   ///< SD card
    BLOCK_DEV_SMXD,                 ///< SM or xD card
    BLOCK_DEV_NAND,                 ///< Nand
    BLOCK_DEV_NOR,                  ///< Nor
    BLOCK_DEV_TOTAL                 ///< Type count of supported devices
} BLOCK_DEV_TYPE;

/// Notify settings
typedef struct _BLOCK_NOTIFY_T
{
    BLOCK_CALLBACK  pfnHandler;     ///< Notify handler
    UINT32          u4Tag;          ///< Tag of notify handler
} BLOCK_NOTIFY_T;

/// The information of all connected devices
typedef struct _BlockDevConnectInfo
{
    HANDLE_T        hDevId;         ///< Handle of the device id
    BLOCK_DEV_TYPE  rType;          ///< Type of the block device (usb, ms...)
    BOOL            fActive;        ///< Device is active now
    UINT32          u4Lun;          ///< Lun No
    INT64           i8Size;         ///< Device size
    UINT8           *pModelName;    ///< Model name
} BlockDevConnectInfo_T;


//-----------------------------------------------------------------------------
// Prototype  of public functions
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
/** Set the notify handler if the medium is inserted or removed
 *
 *  @param  prSetNotify     Structure address of the notify setting
 *
 *  @retval FAT_E_OK        Succeed
 *  @retval FAT_E_FAIL      Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrSetHotSwapNotify(const BLOCK_NOTIFY_T *prSetNotify);

//-----------------------------------------------------------------------------
/** Get the size of the selected device
 *
 *  @param  pDeviceList     Memory address of the size value
 *
 *  @retval BLKMGR_E_OK     Succeed
 *  @retval BLKMGR_E_FAIL   Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrGetSize(INT64 *pi8Size);

//-----------------------------------------------------------------------------
/** Get the status of the selected device (connected or offline)
 *
 *  @param  pi4Status       Memory address of the device status
 *
 *  @retval BLKMGR_E_OK     Succeed
 *  @retval BLKMGR_E_FAIL   Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrGetStatus(INT32 *pi4Status);

//-----------------------------------------------------------------------------
/** Get the model name of the selected device
 *
 *  @param  pu1ModelName    Memory address of the model name buffer
 *  @param  u4BuffLen       The size of the model name buffer
 *
 *  @retval BLKMGR_E_OK     Succeed
 *  @retval BLKMGR_E_FAIL   Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrGetModel(UINT8 *pu1ModelName, UINT32 u4BuffLen);

//-----------------------------------------------------------------------------
/** Erase the selected device
 *
 *  @param  u8Offset        The offset address of the selected device
 *  @param  u4MemLen        The erase byte count
 *
 *  @retval BLKMGR_E_OK     Succeed
 *  @retval BLKMGR_E_FAIL   Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrErase(UINT64 u8Offset, UINT32 u4ByteCount);

//-----------------------------------------------------------------------------
/** Read the selected device
 *
 *  @param  u8Offset        The offset address of the selected device
 *  @param  u4MemLen        The lengh of the read buffer
 *  @param  u4MemPtr        The address of the read buffer
 *
 *  @retval BLKMGR_E_OK     Succeed
 *  @retval BLKMGR_E_FAIL   Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrRead(UINT64 u8Offset, UINT32 u4MemLen, UINT32 u4MemPtr);

//-----------------------------------------------------------------------------
/** Write the selected device
 *
 *  @param  u8Offset        The offset address of the selected device
 *  @param  u4MemLen        The lengh of the write buffer
 *  @param  u4MemPtr        The address of the write buffer
 *
 *  @retval BLKMGR_E_OK     Succeed
 *  @retval BLKMGR_E_FAIL   Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrWrite(UINT64 u8Offset, UINT32 u4MemLen, UINT32 u4MemPtr);

//-----------------------------------------------------------------------------
/** Allocate resource, initial internal states and start the block manager
 *
 *  @retval BLKMGR_E_OK     Succeed
 *  @retval BLKMGR_E_FAIL   Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrInit(void);

//-----------------------------------------------------------------------------
/** Stop the block manager and release all resource
 *
 *  @retval BLKMGR_E_OK     Succeed
 *  @retval BLKMGR_E_FAIL   Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrUninit(void);

//-----------------------------------------------------------------------------
/** Connect the selected device and open it
 *
 *  @param  hDevId          Selected device handle
 *
 *  @retval BLKMGR_E_OK     Succeed
 *  @retval BLKMGR_E_FAIL   Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrDeviceConnect(HANDLE_T hDevId);

//-----------------------------------------------------------------------------
/** Disconnect the selected device
 *
 *  @param  hDevId          Selected device handle
 *
 *  @retval BLKMGR_E_OK     Succeed
 *  @retval BLKMGR_E_FAIL   Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrDeviceDisconnect(HANDLE_T hDevId);

//-----------------------------------------------------------------------------
/** Get the list of all connecting block devices
 *
 *  @param  pu4ConnectDevNo Total number of the connected device
 *  @param  pDeviceList     Memory address of the device list buffer
 *
 *  @retval BLKMGR_E_OK     Succeed
 *  @retval BLKMGR_E_FAIL   Fail
 */
//-----------------------------------------------------------------------------
extern INT32 BlockMgrGetConnectDeviceList(UINT32 *pu4ConnectDevNo,
                                          BlockDevConnectInfo_T **pDeviceList);

#endif  // BLKMGR_IF_H
