#ifndef _SD_CARD_H
#define _SD_CARD_H
#include "include.h"

#define sd_send_cmd_no_rsp(sdcb, index, arg)      sdio_req(sdcb, index |0x40, arg, SDIO_RESPONSE_NO, 0, 1)
#define sd_send_cmd_r1(sdcb, index, arg)          sdio_req(sdcb, index | 0x40, arg, SDIO_RESPONSE_SHORT, 0, 1)         //接收6BYTE
#define sd_send_cmd_r1b(sdcb, index, arg)         sdio_req(sdcb, index | 0x40, arg, SDIO_RESPONSE_SHORT, 1, 1)         //接收6BYTE，并等待BUSY
#define sd_send_cmd_r2(sdcb, index, arg)          sdio_req(sdcb, index | 0x40, arg, SDIO_RESPONSE_LONG, 0, 1)          //接收17BYTE
#define sd_send_cmd_r3(sdcb, index, arg)          sdio_req(sdcb, index | 0x40, arg, SDIO_RESPONSE_SHORT, 0, 1)         //接收6BYTE
#define sd_send_cmd_r6(sdcb, index, arg)          sdio_req(sdcb, index | 0x40, arg, SDIO_RESPONSE_SHORT, 0, 1)         //接收6BYTE
#define sd_send_cmd_r7(sdcb, index, arg)          sdio_req(sdcb, index | 0x40, arg, SDIO_RESPONSE_SHORT, 0, 1)         //接收6BYTE
#define sd_send_cmd_mult_read(sdcb, index, arg)   sdio_req(sdcb, index | 0x40, arg, SDIO_RESPONSE_SHORT, 0, 0)    //多块读时，不需要增加8CLK。其实，多块读先KICK DATA，这个是无所谓的


enum {
    DEV_STA_DISONLINE,  //设备不在线
    DEV_STA_NEW,        //设备未初始化，需要进行初始化
    DEV_STA_OK,         //设备OK，可以正常读取
    DEV_STA_INVALID,    //设备无效
};

enum {
    TYPE_INVALID,       //不支持
    TYPE_SD_1,          //SD 1.0
    TYPE_SD_2,          //SD 2.0
    TYPE_MMC,           //MMC
};

enum {
    RW_IDLE,            //空闲状态
    RW_READ,            //读状态
    RW_WRITE,           //写状态
};

struct _sdcb_t;

typedef struct _sdcfg_t {
    u16 go_ready_retry;         //等待激活就绪时间
    u8 identification_retry;    //卡类别鉴定重试次数
    u8 rw_retry;                //读写重试次数设置, 可能不重新初始化SD卡.
    u8 rw_init_retry;           //读写重试次数设置, 失败后,会重新初始化SD卡去retry
    u8 stop_retry;              //STOP重试次数设置
    u8 rw_need_stop;            //每次读写是否需要STOP.   //BIT(0)=1表示每次读需要stop,  BIT(1) = 1表示每次写都需要STOP.
} sdcfg_t;

typedef struct _sdfunc_t {
    bool (*read_wait)(struct _sdcb_t *sdcb);
    bool (*write_wait)(struct _sdcb_t *sdcb);
    void (*port_init)(u8 type);             //SD IO初始化
} sdfunc_t;

typedef struct _sdcard_t {
    u32 rca;                                //RCA Addr
    struct {
        uint abend              :1;         //异常标志
        uint con                :4;		    //控制器编号：1和2
        uint use_4bit           :1;         //芯片是否使用4BIT通信
        uint support_4bit       :1;         //SD卡是否支持4BIT通信
        uint flag_w2dat         :1;
        uint reserved_1         :2;         //保留2BIT
        uint online             :1;
        uint flag_sdhc          :1;         //高速卡标志


        //卡的常用信息
        uint type               :4;         //Card Type
        uint sta                :4;         //SD卡的状态

        uint reserved_2         :8;         //保留8BIT

        //以下处理连续读
        uint rw_sta           :4;           //上一次读写状态
    };
    u32 rw_lba;                             //下一个连续的读写地址

    //容量
    u32 capacity;
} sdcard_t;

//SD Control Block
typedef struct _sdcb_t {
    sdfunc_t *sdfunc;
    sdcfg_t *sdcfg;         //SD控制器的一些配置
    sdcard_t card;          //SD卡的一些状态
} sdcb_t;

bool sdio_req(sdcb_t *sdcb, uint8_t cmd, uint32_t arg, SDIO_RESPONSE_TYPEDEF rsp_type, FLAG_STATE ccbusy_en, FLAG_STATE ck8_en );
bool sdio_req_pending(sdcb_t *sdcb);
void sdio_read_kick(sdcb_t *sdcb, void *buf);
void sdio_write_kick(sdcb_t *sdcb, void *buf);
bool sdio_isbusy(sdcb_t *sdcb);
void sd_go_idle_state(sdcb_t *sdcb);
bool mmc_send_op_cond(sdcb_t *sdcb);
bool mmc_send_op_cond(sdcb_t *sdcb);
void sd_req_all_send_cid(sdcb_t *sdcb);
void sd_send_relative_addr(sdcb_t *sdcb);
void mmc_set_relative_addr(sdcb_t *sdcb);
void sd_relative_addr_auto(sdcb_t *sdcb);
void sd_select_card(sdcb_t *sdcb);
bool sd_req_send_if_cond(sdcb_t *sdcb);
void get_sd_capacity(sdcb_t *sdcb);
void get_mmc_capacity(sdcb_t *sdcb);
void sd_req_send_csd(sdcb_t *sdcb);
void sd_stop_transmission(sdcb_t *sdcb);
void sd_send_status(sdcb_t *sdcb);
bool sd_read_multiple_block(sdcb_t *sdcb, u32 lba);
bool sd_write_multiple_block(sdcb_t *sdcb, u32 lba);
bool sd_app_cmd(sdcb_t *sdcb);
bool sd_send_op_cond_0(sdcb_t *sdcb);
bool sd_send_op_cond_1(sdcb_t *sdcb);
void sdcfg_init(sdcfg_t *sdcfg);
void sd_gpio_init_ex(u8 type);
void sdfunc_init(sdfunc_t *sdfunc);
void sd_sdio_init(sdcb_t *sdcb);
bool sd_type_identification(sdcb_t *sdcb);
bool sd_go_ready_try(sdcb_t *sdcb);
bool sd_go_ready(sdcb_t *sdcb);
bool sd_try_init(sdcb_t *sdcb);
bool sd_init(sdcb_t *sdcb);

void sd_read_send_cmd(sdcb_t *sdcb, uint lba);
void sd_read_start(sdcb_t *sdcb, void *buf, u32 lba);
bool sd_read_try(sdcb_t *sdcb, void *buf, u32 lba);
bool sd_read(sdcb_t *sdcb, void *buf, u32 lba);
void sd_write_send_cmd(sdcb_t *sdcb, u32 lba);
void sd_write_start(sdcb_t *sdcb, void* buf, u32 lba);
bool sd_write_try(sdcb_t *sdcb, void* buf, u32 lba);
bool sd_write(sdcb_t *sdcb, void* buf, u32 lba);
bool sd_stop(sdcb_t *sdcb, bool type);
u32 get_sd_cid_flag(void);

#endif
