// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : ucp_pcie_traffic.h
// Author        : xianfeng.du
// Created On    : 2022-06-25
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------

#ifndef __PCIE_TRAFFIC_H__
#define __PCIE_TRAFFIC_H__

#include "dw_pcie_ep.h"
#include "msg_transfer_queue.h"

#define MAX_CH_NUM_UCP_DMA    MAX_CH_NUM_DW_DMA
#define MAX_THREAD_NUM_UCP_DMA  128 //32 //

#define MAX_DESC_NUM  128

#define MAX_Q_NUM_DL_TRAFFIC UCP4008_TRAFFIC_MAX_NUM
#define MAX_Q_NUM_UL_TRAFFIC UCP4008_TRAFFIC_MAX_NUM


//DMA通道的状态以及服务的traffic的thread idx号
typedef union DmaChStateIdx {
    uint32_t value;
    struct {
        uint16_t state;
        uint16_t thread_Idx;
    };
} DmaChStateIdx_t;


typedef enum eUcpPcieDmaState {
    UCP_DMA_STATE_IDLE,
    UCP_DMA_STATE_WORKING,
    UCP_DMA_STATE_FINISHED
} UcpPcieDmaState_e;

typedef enum ePcieEpStatusType {
	epInit = 1,
	epReady,
	epRunning
} PcieEpStatusType_e;

typedef struct tUcpPcieDmaServiceTraffic {
    uint32_t served_traffic_insid;//小区号
	uint32_t served_traffic_queid;//queue
    uint32_t thread_idx;	
} UcpPcieDmaServiceTraffic_t;

//DMA通道状态结构体
typedef struct tUcpPcieDmaChannel {
    UcpPcieDmaState_e   state;//DMA通道的状态、空闲还是忙
    UcpPcieDmaServiceTraffic_t served_traffic; //本次DMA通道传输所服务的traffic号
    uint32_t *finished; //是否已经传输完成
} UcpPcieDmaCh_t;

typedef struct tUcpPcieDmaComplete {
    uint32_t finished;
    uint32_t extInc;//传输的数据包个数
    uint32_t intInc;
} UcpPcieDmaComplete_t;

//DMA线程
typedef struct tUcpPcieDmaThread {
    uint32_t size;
    uint32_t mask;//thread一共32个是循环使用的，该用来对in和out进行取模，用取模结果索引到thread，模值是从0开始，因此是31
    uint32_t in; //用来表示该通道开始启动DMA传输
    uint32_t out; //用来表示通道的DMA传输已经完成，如果
    UcpPcieDmaComplete_t thread[MAX_THREAD_NUM_UCP_DMA];
} UcpPcieDmaThread_t;

//跟应用通信的结构体
typedef struct tUcpExternalTraffic {
    uint32_t mask;//DMA描述符的mask，DMA描述符是环形循环使用，每个通道最大128
    uint32_t epCntIng;//通道收到是数据包的个数计数累加，最大128，因此需要用127取模
    uint32_t* buf; // point to start of buffer，实际收发的数据包
    uint32_t  offset; // offset to buf to hold next data segment
    uint8_t  lastEop; // EOP of last data segment
    UcpPcieDmaThread_t dma;
} UcpExtTraffic_t;

//PCIE的链路状态
typedef struct tPcieLinkStatus {
	uint32_t devEnable;
	uint32_t devReady;
} PcieLinkStatus_t;

//RC和EP通信的counter结构体
typedef struct tPcieTrafficCounter {
	uint32_t dlDescNum[MAX_INSTANCE_NUM][MAX_Q_NUM_DL_TRAFFIC];//通道描述符的个数，固定为128
	uint32_t dlTxCounter[MAX_INSTANCE_NUM][MAX_Q_NUM_DL_TRAFFIC];//由RC侧来填充，RC侧写下来的数据包的个数
	uint32_t dlRxCounter[MAX_INSTANCE_NUM][MAX_Q_NUM_DL_TRAFFIC];//EP侧接收到的数据包的个数
	//int8_t dlDescIdx[MAX_Q_NUM_DL_TRAFFIC][MAX_DESC_NUM];//该通道的DMA描述符的索引计数，最大128

	uint32_t ulDescNum[MAX_INSTANCE_NUM][MAX_Q_NUM_UL_TRAFFIC];//通道描述符的个数，固定为12s8
	uint32_t ulTxCounter[MAX_INSTANCE_NUM][MAX_Q_NUM_UL_TRAFFIC];//EP侧发送出去的数据包个数
	uint32_t ulRxCounter[MAX_INSTANCE_NUM][MAX_Q_NUM_UL_TRAFFIC];//RC填充，RC接收到的数据包的个数
	//int8_t ulDescIdx[MAX_Q_NUM_UL_TRAFFIC][MAX_DESC_NUM];//该通道的DMA描述符的索引计数，最大128	
} PcieTrafficCounter_t;

/*
typedef struct tPcieEpCounterMirror {
	volatile uint32_t dlRxCounter[MAX_Q_NUM_DL_TRAFFIC];
	volatile uint32_t ulTxCounter[MAX_Q_NUM_UL_TRAFFIC];
} PcieEpCounterMirror_t __attribute__((__aligned__(NPU_CACHE_LINE_SZ)));
*/
//RC和EP通信的用于配置DMA的描述符，由RC来填充phyAddr和length
typedef struct tPcieTraffiDescriptor {
    uint64_t phyAddr;  // pointer to start physical address of a buffer in NPU memory
    uint32_t length;    // length of content to be sent in bytes
    uint8_t  eop;       // end of packet, 0=not the last descriptor for a whole message, 1=last descriptor
    uint8_t  type;      // packet type, 0=data, 1=control for data, 2=other control, this field is not used for OAM & FH
    uint16_t rsv;
} PcieTrafficDescriptor_t;

//一共对传输描述符，用于9种业务，由收发task进行处理
typedef struct tUcpTaskDescriptor{
    PcieTrafficDescriptor_t  dl[MAX_INSTANCE_NUM][MAX_Q_NUM_DL_TRAFFIC][MAX_DESC_NUM];
    PcieTrafficDescriptor_t  ul[MAX_INSTANCE_NUM][MAX_Q_NUM_UL_TRAFFIC][MAX_DESC_NUM];
} UcpTaskDescriptor_t;

//pcie command enum
typedef enum pcieCommandType{
	PCI_ENDPOINT_UCPEP_MAGIC,
	PCI_ENDPOINT_UCPEP_COMMAND,
	PCI_ENDPOINT_UCPEP_EP_ED,
	PCI_ENDPOINT_UCPEP_RC_STATUS,
	PCI_ENDPOINT_UCPEP_EP_STATUS,
	PCI_ENDPOINT_UCPEP_DMA_STATUS,
	PCI_ENDPOINT_UCPEP_UPPER_DST_ADDR,
	PCI_ENDPOINT_UCPEP_SIZE,
	PCI_ENDPOINT_UCPEP_CHECKSUM,
	PCI_ENDPOINT_UCPEP_IRQ_TYPE,
	PCI_ENDPOINT_UCPEP_IRQ_NUMBER,
	PCI_ENDPOINT_UCPEP_TIME_L,
	PCI_ENDPOINT_UCPEP_TIME_R,
	PCI_ENDPOINT_UCPEP_TEST,
}pcieCommand;
#define PCI_UCPEP_EP_HEARTBEAT        0x5A5A5A5A
#define PCI_UCPEP_RC_HEARTBEAT        0xA5A5A5A5
#define PCI_HEARTBEAT_MAXTIME         100


//bar空间的数据结构体，用来存放bar空间的收发计数，DMA的ll描述符
typedef struct tPcieEpMemBarStruct {
	PcieLinkStatus_t     status;//PCIE链路状态      地址 0x08740000   // 8字节
	SyncInfo_t		 	 trafficSyncInfo;	//   0x08740000+8  //
	transfer_type_info_s traffic[MAX_INSTANCE_NUM][TRANSFER_TYPE_NUM];//业务配置下来的按照业务配置信息  0x08740000+ 0x18               //（8+16)字节 
	PcieTrafficCounter_t cnt; //每个通道本次收发数据包状态结构体 //0x08740000+ 0x1F8  //(8+16+480)字节
	UcpTaskDescriptor_t  desc;//RC和EP之间DMA任务收发数据的描述符，//  6*128*2=  1536字节//  0x08740000+ 0x288                  (8+16+480+144)= 648
	uint32_t             command[14];//RC和EP通信的command的命令, //  0x08740000+ 0x888                  88A=(8+16+480+144+1536)= 2184
	char 				 log_buf[1024];//用于将EP侧log输出到RC侧
} PcieEpMemBarStruct_t;

//PCIE的根结构体
typedef struct tUcpPcieEpMemInfo {
    PcieEpMemBarStruct_t*   	pUcpMemBar;//bar空间结构体，用于RC和EP之间进行信息传递，
	
	DwPcieDmaLinkListNode_t*	pDmaDesc;//DMA Link list描述符，用于DMA传输对数据包的链表信息资源
	
    UcpPcieDmaCh_t*         	pDmaDlCh[MAX_CH_NUM_UCP_DMA];//DMA下行通道状态，通道所服务的业务id
    UcpPcieDmaCh_t*         	pDmaUlCh[MAX_CH_NUM_UCP_DMA];//DMA上行通道状态，通道所服务的业务id
	
    PcieDmaBuffer_t*  			pRdmaChains[MAX_CH_NUM_UCP_DMA];//读通道buffer，用于DMA传输的LL链表
    PcieDmaBuffer_t*  			pWdmaChains[MAX_CH_NUM_UCP_DMA];//写通道buffer，通道所服务的业务id
	
    UcpExtTraffic_t*        	pExtDlTraffic[MAX_INSTANCE_NUM][UCP4008_TRAFFIC_MAX_NUM];//[MAX_Q_NUM_DL_TRAFFIC]; //下行应用业务通信结构体
    UcpExtTraffic_t*        	pExtUlTraffic[MAX_INSTANCE_NUM][UCP4008_TRAFFIC_MAX_NUM];//[MAX_Q_NUM_UL_TRAFFIC]; //上行应用业务通信结构体	
} UcpPcieEpMemInfo_t;

UcpPcieEpMemInfo_t* get_ucp_pcie_mem_info(void);
void ucp_pcie_worker(void);
void ucp_pcie_reset(void);
int ucp_pcie_recfg_reset(void);

void ucp_pcie_reset_bar(void);
void debug_log(uint8_t level, const char *fmt, ...);
void no_debug_log(const char *fmt, ...);

void ucp_testSpeed_pcie_worker(void);

#define PCIE_ERROR_LOG(fmt, args...)  debug_log(LOG_ERROR, "[ERROR]:" fmt "\n", ##args)  //debug_log(fmt, ##args)

//#define PCIE_DEBUG_LOG(fmt, args...)   debug_log(fmt, ##args) 

#define PCIE_DEBUG_LOG(fmt, args...)     debug_log(LOG_DEBUG, "[PCIE_LOG]:" fmt "\n", ##args) //no_debug_log(fmt, ##args)

#endif
