/**************************************************************************//**
 * @file     GNAND_Global.h
 * @version  V3.00
 * @brief    N9H20 series GNAND driver header file
 *
 * SPDX-License-Identifier: Apache-2.0
 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/

/* Changelog:
 * Base on GNAND library v1.01
 *
 * 2011/02/18
 *          To support new feature wear-leveling.
 *
 * 2011/04/27
 *          Backward compatible to GNAND format version V1.00 and V1.01 on NAND chip
 */

#ifndef _GNAND_GLOBAL_H_
#define _GNAND_GLOBAL_H_

//#define DBG_MSG       printf
//#define DBG_MSG       sysprintf
#define DBG_MSG(...)

// DBG_INFO() should show minimum information for RD under development stage.
//      For example, GNAND version, fetal error, critical check point, and so on.
#define DBG_INFO        sysprintf

#define FREE_BLOCK          0xFFFF
#define BAD_BLOCK           0xFFF0
#define OP_BLOCK            0xFFAA
#define L2PN_BLOCK          0xFF55
#define P2LN_BLOCK          0xFF55

/* global string define */
#define P2LN_INFO_MAGIC         "GNAND"

// P2LN_INFO_VERSION means the version of GNAND data format on NAND chip.
#define P2LN_INFO_VERSION       "V1.01"
#define P2LN_INFO_VERSION_OLD   "V1.00"
#define P2LN_INFO_DATE          "20101125_0"

#define P2LN_INFO_T     struct p2ln_info_t

struct p2ln_info_t
{
    CHAR    magic[8];       /* "GNAND"                               */
    CHAR    version[8];     /* "V1.00"                               */
    CHAR    date_code[16];  /* for example: "20080220_1"             */
    UINT16  op_block;       /* OP block address                      */
    UINT16  old_op_block;   /* Old OP block address                  */
    UINT16  old_p2ln;       /* old P2LN block address                */
    UINT16  old_p2ln1;      /* old P2LN1 block address               */
    UINT32  block;          /* block per zone                        */
};


/*-------------------------------------------------------------------*/
/* Operation history                                                 */
/*-------------------------------------------------------------------*/
#define OP_LINK         "LINK"
#define OP_RELINK       "RELINK"
#define OP_P2LN         "P2LN"

#define GNOP_LINK_T     struct gnop_link_t
#define GNOP_RELINK_T   struct gnop_relink_t
#define GNOP_P2LN_T     struct gnop_p2ln_t

struct gnop_link_t
{
    CHAR    op[8];          /* string "LINK"  */
    UINT16  lba;
    UINT16  pba;
    CHAR    reserved[20];
} ;


struct gnop_relink_t
{
    CHAR    op[8];          /* string "RELINK" */
    UINT16  lba;
    UINT16  old_pba;
    UINT16  new_pba;
    UINT16  start_page;
    UINT16  page_cnt;
    UINT16  check_mark;
    CHAR    reserved[12];
} ;


struct gnop_p2ln_t
{
    CHAR    op[8];          /* string "P2LN" */
    UINT16  old_p2ln;
    UINT16  old_op;
    UINT16  new_p2ln;
    UINT16  new_op;
    UINT16  old_p2ln1;
    UINT16  new_p2ln1;
    CHAR    reserved[12];
} ;


/*-------------------------------------------*/
/* global variable extern                    */
/*-------------------------------------------*/
extern UINT8 *_gnand_pDMABuffer;
extern UINT8 *_gnand_pUBBuffer;

//--- To support new feature wear-leveling
// all 3 global variables support up to 8 zones that like as db_idx[16] in struct ndisk_t
extern UINT32 age_sum[16];             // sum of age of all valid blocks
extern UINT16 valid_block_count[16];   // number of all valid blocks
extern UINT16 age_average[16];         // average of age of all valid blocks = (UINT16)(age_sum[zone] / valid_block_count[zone])

/*-------------------------------------------------------------------*/
/* Export functions (GNAND library internal)                         */
/*-------------------------------------------------------------------*/
INT  GNAND_OP_LinkNew(NDISK_T *ptNDisk, UINT16 LBlockAddr, UINT16 *PBlockAddr);
INT  GNAND_OP_ReLink(NDISK_T *ptNDisk, UINT16 LBlockAddr, UINT16 *PBlockAddr, INT nStartPage, INT nPageCnt, BOOL bIsBegin);
INT  GNAND_OP_ReCover(NDISK_T *ptNDisk, UINT16 LBlockAddr, INT nStartPage, INT nPageCnt);
INT  GNAND_OP_P2LN(NDISK_T *ptNDisk);
INT  GNAND_UpdateP2LN(NDISK_T *ptNDisk);
INT  GNAND_IsValidP2LN(NDISK_T *ptNDisk, UINT16 pba, P2LN_INFO_T *p2ln_info);

INT  GNAND_ParseNandROM(NDISK_T *ptNDisk);
INT  GNAND_ParseNandDisk(NDISK_T *ptNDisk, BOOL bEraseIfNotGnandFormat);
INT  GNAND_get_new_data_block(NDISK_T *ptNDisk, UINT16 LBlockAddr, UINT16 *PBlockAddr);
INT  GNAND_check_empty(NDISK_T *ptNDisk, INT PBA);

VOID  GNAND_DirtyPageSet(NDISK_T *ptNDisk, INT pba, INT page);
VOID  GNAND_DirtyPageClear(NDISK_T *ptNDisk, INT pba, INT page);
VOID GNAND_DirtyPageClearBlock(NDISK_T *ptNDisk, INT pba);

extern VOID fsDumpBufferHex(UINT8 *pucBuff, INT nSize);

INT GNAND_show_op(NDISK_T *ptNDisk);
INT GNAND_show_l2pm(NDISK_T *ptNDisk);

#endif  /* _GNAND_GLOBAL_H_ */