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

#ifndef __DW_PCIE_EP_H__
#define __DW_PCIE_EP_H__

#include "typedef.h"
#include "ucp_utility.h"

#define MAX_CH_NUM_DW_DMA 6
#define MAX_NODE_NUM_DMA_CHAIN  (MAX_THREAD_NUM_UCP_DMA + 1) //实际数据包是32个描述符，再加上一个描述符链表的结束描述符，因此需要33个描述符

#define BIT(x) (1U << x)

#define DW_PCIE_EP_DMA_LL_CB BIT(0)
#define DW_PCIE_EP_DMA_LL_TCB BIT(1)
#define DW_PCIE_EP_DMA_LL_LLP BIT(2)
#define DW_PCIE_EP_DMA_LL_LIE BIT(3)
#define DW_PCIE_EP_DMA_LL_RIE BIT(4)

#define DW_PCIE_DMA_CH_UNR_LOCAL_IRQ BIT(3)
#define DW_PCIE_DMA_CH_UNR_REMOTE_IRQ BIT(4)

#define DW_PCIE_SHANDOW_BASE_ADDR 0x100000      //PCIE shandow寄存器基址，用来存放bar空间的size
#define DW_PCIE_IATU_BASE_ADDR    0x300000      //PCIE IATU基址
#define PFO_DMA_CAP_REG_BASE_ADDR 0x380000      //PCIE DMA基址
#define DW_PCIE_DBI_BASE              0xC000000 //PCIE_DBI_BASE

#define DW_PCIE_WDMA_STATUS_OFF 0x04C
#define DW_PCIE_RDMA_STATUS_OFF 0x0A0
#define DW_PCIE_DMA_UNR_INT_STATUS_OFF 0x0
#define DW_PCIE_DMA_UNR_INT_MASK_OFF 0x8
#define DW_PCIE_DMA_UNR_INT_CLEAR_OFF 0xC

#define DW_PCIE_WDMA_UNR_INT_ERR_OFF 0x10
#define DW_PCIE_WDMA_UNR_LL_ERR_EN_OFF 0x44
#define DW_PCIE_RDMA_UNR_INT_ERR_OFF 0x14
#define DW_PCIE_RDMA_UNR_INT_ERR1_OFF 0x18
#define DW_PCIE_RDMA_UNR_LL_ERR_EN_OFF 0x24

#define DW_PCIE_WDMA_STATUS_MSI_REG_OFF 0x14
#define DW_PCIE_RDMA_STATUS_MSI_REG_OFF 0x2C
#define DW_PCIE_DMA_STATUS_MSI_UNR_DONE_ADDR_LOW_OFF 0x0
#define DW_PCIE_DMA_STATUS_MSI_UNR_DONE_ADDR_HIGH_OFF 0x4
#define DW_PCIE_DMA_STATUS_MSI_UNR_ABORT_ADDR_LOW_OFF 0x8
#define DW_PCIE_DMA_STATUS_MSI_UNR_ABORT_ADDR_HIGH_OFF 0xC
#define DW_PCIE_DMA_STATUS_MSI_UNR_CH_DATA_OFF(ch) ((((ch) >> 1)<<2) + 0x10)

#define DW_PCIE_DMA_CH_UNR_CTRL1_OFF 0x0
#define DW_PCIE_DMA_CH_UNR_CTRL2_OFF 0x4
#define DW_PCIE_DMA_CH_UNR_SIZE_OFF 0x8
#define DW_PCIE_DMA_CH_UNR_SAR_LOW_OFF 0xC
#define DW_PCIE_DMA_CH_UNR_SAR_HIGH_OFF 0x10
#define DW_PCIE_DMA_CH_UNR_DAR_LOW_OFF 0x14
#define DW_PCIE_DMA_CH_UNR_DAR_HIGH_OFF 0x18
#define DW_PCIE_DMA_CH_UNR_LLP_LOW_OFF 0x1C
#define DW_PCIE_DMA_CH_UNR_LLP_HIGH_OFF 0x20

#define DW_PCIE_DMA_CTRL_OFF 0x000
#define DW_PCIE_DMA_UNR_EABLE_OFF 0x00C
#define DW_PCIE_DMA_UNR_DOORBELL_OFF 0x010
#define DW_PCIE_DMA_UNR_ARB_WEIGHT_LOW_OFF 0x018
#define DW_PCIE_DMA_UNR_ARB_WEIGHT_HIGH_OFF 0x01C
		
#define DW_PCIE_WDMA_CTRL_REG_OFF(reg) (reg)
#define DW_PCIE_RDMA_CTRL_REG_OFF(reg) (reg | BIT(5))
#define DW_PCIE_WDMA_CH_REG_OFF(ch) (((ch)+1) << 9)      //i*0x200+0x200
#define DW_PCIE_RDMA_CH_REG_OFF(ch) ((((ch)+1) << 9) | BIT(8))  //i*0x200+0x300
#define DW_PCIE_DMA_CH_STATUS(ctrl) (((ctrl) >> 5) & 0x3)  //channel status      

#define DW_PCIE_DMA_APP_ERR BIT(0)
#define DW_PCIE_DMA_LINKLIST_ERR BIT(1)
#define DW_PCIE_DMA_UNSUPPORTED_REQ_ERR BIT(2)
#define DW_PCIE_DMA_CPL_ABORT_ERR BIT(3)
#define DW_PCIE_DMA_CPL_TIMEOUT_ERR BIT(4)
#define DW_PCIE_DMA_DATA_POISION_ERR BIT(5)

//add by gyl
#define DMA_CTRL_DATA_ARB_PRIOR_OFF                            (0x0)
#define DMA_CTRL_OFF                                           (0x8)
#define DMA_WRITE_ENGINE_EN_OFF                                (0xc)
#define DMA_WRITE_DOORBELL_OFF                                 (0x10)
#define DMA_WRITE_CHANNEL_ARB_WEIGHT_LOW_OFF                   (0x18)
#define DMA_WRITE_CHANNEL_ARB_WEIGHT_HIGH_OFF                  (0x1c)
#define DMA_READ_ENGINE_EN_OFF                                 (0x2c)
#define DMA_READ_DOORBELL_OFF                                  (0x30)
#define DMA_READ_CHANNEL_ARB_WEIGHT_LOW_OFF                    (0x38)
#define DMA_READ_CHANNEL_ARB_WEIGHT_HIGH_OFF                   (0x3c)
#define DMA_WRITE_INT_STATUS_OFF                               (0x4c)
#define DMA_WRITE_INT_MASK_OFF                                 (0x54)
#define DMA_WRITE_INT_CLEAR_OFF                                (0x58)
#define DMA_WRITE_ERR_STATUS_OFF                               (0x5c)
#define DMA_WRITE_DONE_IMWR_LOW_OFF                            (0x60)
#define DMA_WRITE_DONE_IMWR_HIGH_OFF                           (0x64)
#define DMA_WRITE_ABORT_IMWR_LOW_OFF                           (0x68)
#define DMA_WRITE_ABORT_IMWR_HIGH_OFF                          (0x6c)
#define DMA_WRITE_CH01_IMWR_DATA_OFF                           (0x70)
#define DMA_WRITE_CH23_IMWR_DATA_OFF                           (0x74)
#define DMA_WRITE_CH45_IMWR_DATA_OFF                           (0x78)
#define DMA_WRITE_CH67_IMWR_DATA_OFF                           (0x7c)
#define DMA_WRITE_LINKED_LIST_ERR_EN_OFF                       (0x90)
#define DMA_READ_INT_STATUS_OFF                                (0xa0)
#define DMA_READ_INT_MASK_OFF                                  (0xa8)
#define DMA_READ_INT_CLEAR_OFF                                 (0xac)
#define DMA_READ_ERR_STATUS_LOW_OFF                            (0xb4)
#define DMA_READ_ERR_STATUS_HIGH_OFF                           (0xb8)
#define DMA_READ_LINKED_LIST_ERR_EN_OFF                        (0xc4)
#define DMA_READ_DONE_IMWR_LOW_OFF                             (0xcc)
#define DMA_READ_DONE_IMWR_HIGH_OFF                            (0xd0)
#define DMA_READ_ABORT_IMWR_LOW_OFF                            (0xd4)
#define DMA_READ_ABORT_IMWR_HIGH_OFF                           (0xd8)
#define DMA_READ_CH01_IMWR_DATA_OFF                            (0xdc)
#define DMA_READ_CH23_IMWR_DATA_OFF                            (0xe0)
#define DMA_READ_CH45_IMWR_DATA_OFF                            (0xe4)
#define DMA_READ_CH67_IMWR_DATA_OFF                            (0xe8)
#define DMA_CH_CONTROL1_OFF_WRCH_0                             (0x200)
#define DMA_TRANSFER_SIZE_OFF_WRCH_0                           (0x208)
#define DMA_SAR_LOW_OFF_WRCH_0                                 (0x20c)
#define DMA_SAR_HIGH_OFF_WRCH_0                                (0x210)
#define DMA_DAR_LOW_OFF_WRCH_0                                 (0x214)
#define DMA_DAR_HIGH_OFF_WRCH_0                                (0x218)
#define DMA_LLP_LOW_OFF_WRCH_0                                 (0x21c)
#define DMA_LLP_HIGH_OFF_WRCH_0                                (0x220)
#define DMA_CH_CONTROL1_OFF_RDCH_0                             (0x300)
#define DMA_TRANSFER_SIZE_OFF_RDCH_0                           (0x308)
#define DMA_SAR_LOW_OFF_RDCH_0                                 (0x30c)
#define DMA_SAR_HIGH_OFF_RDCH_0                                (0x310)
#define DMA_DAR_LOW_OFF_RDCH_0                                 (0x314)
#define DMA_DAR_HIGH_OFF_RDCH_0                                (0x318)
#define DMA_LLP_LOW_OFF_RDCH_0                                 (0x31c)
#define DMA_LLP_HIGH_OFF_RDCH_0                                (0x320)
#define DMA_CH_CONTROL1_OFF_WRCH_1                             (0x400)
#define DMA_TRANSFER_SIZE_OFF_WRCH_1                           (0x408)
#define DMA_SAR_LOW_OFF_WRCH_1                                 (0x40c)
#define DMA_SAR_HIGH_OFF_WRCH_1                                (0x410)
#define DMA_DAR_LOW_OFF_WRCH_1                                 (0x414)
#define DMA_DAR_HIGH_OFF_WRCH_1                                (0x418)
#define DMA_LLP_LOW_OFF_WRCH_1                                 (0x41c)
#define DMA_LLP_HIGH_OFF_WRCH_1                                (0x420)
#define DMA_CH_CONTROL1_OFF_RDCH_1                             (0x500)
#define DMA_TRANSFER_SIZE_OFF_RDCH_1                           (0x508)
#define DMA_SAR_LOW_OFF_RDCH_1                                 (0x50c)
#define DMA_SAR_HIGH_OFF_RDCH_1                                (0x510)
#define DMA_DAR_LOW_OFF_RDCH_1                                 (0x514)
#define DMA_DAR_HIGH_OFF_RDCH_1                                (0x518)
#define DMA_LLP_LOW_OFF_RDCH_1                                 (0x51c)
#define DMA_LLP_HIGH_OFF_RDCH_1                                (0x520)
#define DMA_CH_CONTROL1_OFF_WRCH_2                             (0x600)
#define DMA_TRANSFER_SIZE_OFF_WRCH_2                           (0x608)
#define DMA_SAR_LOW_OFF_WRCH_2                                 (0x60c)
#define DMA_SAR_HIGH_OFF_WRCH_2                                (0x610)
#define DMA_DAR_LOW_OFF_WRCH_2                                 (0x614)
#define DMA_DAR_HIGH_OFF_WRCH_2                                (0x618)
#define DMA_LLP_LOW_OFF_WRCH_2                                 (0x61c)
#define DMA_LLP_HIGH_OFF_WRCH_2                                (0x620)
#define DMA_CH_CONTROL1_OFF_RDCH_2                             (0x700)
#define DMA_TRANSFER_SIZE_OFF_RDCH_2                           (0x708)
#define DMA_SAR_LOW_OFF_RDCH_2                                 (0x70c)
#define DMA_SAR_HIGH_OFF_RDCH_2                                (0x710)
#define DMA_DAR_LOW_OFF_RDCH_2                                 (0x714)
#define DMA_DAR_HIGH_OFF_RDCH_2                                (0x718)
#define DMA_LLP_LOW_OFF_RDCH_2                                 (0x71c)
#define DMA_LLP_HIGH_OFF_RDCH_2                                (0x720)
#define DMA_CH_CONTROL1_OFF_WRCH_3                             (0x800)
#define DMA_TRANSFER_SIZE_OFF_WRCH_3                           (0x808)
#define DMA_SAR_LOW_OFF_WRCH_3                                 (0x80c)
#define DMA_SAR_HIGH_OFF_WRCH_3                                (0x810)
#define DMA_DAR_LOW_OFF_WRCH_3                                 (0x814)
#define DMA_DAR_HIGH_OFF_WRCH_3                                (0x818)
#define DMA_LLP_LOW_OFF_WRCH_3                                 (0x81c)
#define DMA_LLP_HIGH_OFF_WRCH_3                                (0x820)
#define DMA_CH_CONTROL1_OFF_RDCH_3                             (0x900)
#define DMA_TRANSFER_SIZE_OFF_RDCH_3                           (0x908)
#define DMA_SAR_LOW_OFF_RDCH_3                                 (0x90c)
#define DMA_SAR_HIGH_OFF_RDCH_3                                (0x910)
#define DMA_DAR_LOW_OFF_RDCH_3                                 (0x914)
#define DMA_DAR_HIGH_OFF_RDCH_3                                (0x918)
#define DMA_LLP_LOW_OFF_RDCH_3                                 (0x91c)
#define DMA_LLP_HIGH_OFF_RDCH_3                                (0x920)
#define DMA_CH_CONTROL1_OFF_WRCH_4                             (0xa00)
#define DMA_TRANSFER_SIZE_OFF_WRCH_4                           (0xa08)
#define DMA_SAR_LOW_OFF_WRCH_4                                 (0xa0c)
#define DMA_SAR_HIGH_OFF_WRCH_4                                (0xa10)
#define DMA_DAR_LOW_OFF_WRCH_4                                 (0xa14)
#define DMA_DAR_HIGH_OFF_WRCH_4                                (0xa18)
#define DMA_LLP_LOW_OFF_WRCH_4                                 (0xa1c)
#define DMA_LLP_HIGH_OFF_WRCH_4                                (0xa20)
#define DMA_CH_CONTROL1_OFF_RDCH_4                             (0xb00)
#define DMA_TRANSFER_SIZE_OFF_RDCH_4                           (0xb08)
#define DMA_SAR_LOW_OFF_RDCH_4                                 (0xb0c)
#define DMA_SAR_HIGH_OFF_RDCH_4                                (0xb10)
#define DMA_DAR_LOW_OFF_RDCH_4                                 (0xb14)
#define DMA_DAR_HIGH_OFF_RDCH_4                                (0xb18)
#define DMA_LLP_LOW_OFF_RDCH_4                                 (0xb1c)
#define DMA_LLP_HIGH_OFF_RDCH_4                                (0xb20)
#define DMA_CH_CONTROL1_OFF_WRCH_5                             (0xc00)
#define DMA_TRANSFER_SIZE_OFF_WRCH_5                           (0xc08)
#define DMA_SAR_LOW_OFF_WRCH_5                                 (0xc0c)
#define DMA_SAR_HIGH_OFF_WRCH_5                                (0xc10)
#define DMA_DAR_LOW_OFF_WRCH_5                                 (0xc14)
#define DMA_DAR_HIGH_OFF_WRCH_5                                (0xc18)
#define DMA_LLP_LOW_OFF_WRCH_5                                 (0xc1c)
#define DMA_LLP_HIGH_OFF_WRCH_5                                (0xc20)
#define DMA_CH_CONTROL1_OFF_RDCH_5                             (0xd00)
#define DMA_TRANSFER_SIZE_OFF_RDCH_5                           (0xd08)
#define DMA_SAR_LOW_OFF_RDCH_5                                 (0xd0c)
#define DMA_SAR_HIGH_OFF_RDCH_5                                (0xd10)
#define DMA_DAR_LOW_OFF_RDCH_5                                 (0xd14)
#define DMA_DAR_HIGH_OFF_RDCH_5                                (0xd18)
#define DMA_LLP_LOW_OFF_RDCH_5                                 (0xd1c)
#define DMA_LLP_HIGH_OFF_RDCH_5                                (0xd20)

#define DMA_READ_DONE_MSIX_NUM_CH0		0
#define DMA_WRITE_DONE_MSIX_NUM_CH0		1
#define DMA_READ_BAORT_MSIX_NUM_CH0		2
#define DMA_WRITE_ABORT_MSIX_NUM_CH0	3

#define BAR0_BASE_OF_DBI                                        0x200000
#define MSIX_TABLE_OFF  0
#define PCI_MSIX_ENTRY_SIZE		16
#define PCI_MSIX_ENTRY_LOWER_ADDR	0
#define PCI_MSIX_ENTRY_UPPER_ADDR	4
#define PCI_MSIX_ENTRY_DATA		8
#define PCI_MSIX_ENTRY_VECTOR_CTRL	12
#define PCI_MSIX_ENTRY_CTRL_MASKBIT	1


#define PCI_BASE_ADDRESS_MEM_TYPE_32  0x00
#define PCI_BASE_ADDRESS_MEM_TYPE_64  0x04
#define PCIE_ATU_TYPE_MEM             (0x0 << 0)
#define PCIE_ATU_TYPE_IO              (0X2 << 0)
//atu寄存器偏移地址定义
#define PCIE_ATU_UNR_REGION_CTRL1     0x00
#define PCIE_ATU_UNR_REGION_CTRL2     0x04
#define PCIE_ATU_UNR_LOWER_BASE       0x08
#define PCIE_ATU_UNR_UPPER_BASE       0x0C
#define PCIE_ATU_UNR_LIMIT            0x10
#define PCIE_ATU_UNR_LOWER_TARGET     0x14
#define PCIE_ATU_UNR_UPPER_TARGET     0x18
#define PCIE_ATU_ENABLE               (0x1<<31)
#define PCIE_ATU_BAR_MODE_ENABLE      (0x1<<30)
#define LINK_WAIT_MAX_IATU_RETRIES    5
#define LINK_WAIT_IATU                9

//PCIE配置bar寄存器
#define PCIE_BASE_ADDRESSS_0          0x10
#define PCIE_BASE_ADDRESSS_1          0x14
#define PCIE_BASE_ADDRESSS_2          0x18
#define PCIE_BASE_ADDRESSS_3          0x1c
#define PCIE_BASE_ADDRESSS_4          0x20
#define PCIE_BASE_ADDRESSS_5          0x24

//dbi设置只读寄存器使能
#define PCIE_MISC_CONTROL_1_OFF       0x8BC
#define PCIE_DBI_RO_WR_EN             (0x1 << 0)

//iatu 寄存器基址偏移地址计算， iatu是按照区块分的，一共0~256个区块，每个区块占0x200的空间，前0x100空间为outbound的空间，后0x100为inbound的空间
#define PCIE_IATU_BASE_REG_OFF(region)    (region*0x200)
#define PCIE_IATU_INBOUND_REG_OFF        0x100
#define PCIE_GET_IATU_INBOUND_UNROLL_REG_OFF(region) (PCIE_IATU_BASE_REG_OFF(region) + PCIE_IATU_INBOUND_REG_OFF)


//访问IATU寄存器
#define dw_pcie_read_iatu_reg(region, reg) \
		do_read_volatile(PCIE_GET_IATU_INBOUND_UNROLL_REG_OFF(region) + DW_PCIE_IATU_BASE_ADDR + DW_PCIE_DBI_BASE + (reg))

#define dw_pcie_write_iatu_reg(region, reg, val) \
		do_write(PCIE_GET_IATU_INBOUND_UNROLL_REG_OFF(region) + DW_PCIE_IATU_BASE_ADDR + DW_PCIE_DBI_BASE + (reg), val)
        //*((volatile uint32_t *)(PCIE_GET_IATU_INBOUND_UNROLL_REG_OFF(region) + DW_PCIE_IATU_BASE_ADDR + DW_PCIE_DBI_BASE + (reg))) = (val)

//访问pcie配置空间的shandow寄存器
#define dw_pcie_read_shandow_reg(reg) \
		do_read_volatile(DW_PCIE_SHANDOW_BASE_ADDR + DW_PCIE_DBI_BASE + (reg))

#define dw_pcie_write_shandow_reg(reg, val) \
		do_write(DW_PCIE_SHANDOW_BASE_ADDR + DW_PCIE_DBI_BASE + (reg), val)
       // *((volatile uint32_t *)(DW_PCIE_SHANDOW_BASE_ADDR + DW_PCIE_DBI_BASE + (reg))) = (val)

//访问pcie配置空间寄存器
#define dw_pcie_read_dbi_reg(reg) \
		do_read_volatile(DW_PCIE_DBI_BASE + (reg))

#define dw_pcie_write_dbi_reg(reg, val) \
		do_write(DW_PCIE_DBI_BASE + (reg), val)
      //  *((volatile uint32_t *)(DW_PCIE_DBI_BASE + (reg))) = (val)


//访问DMA寄存器
#define dw_pcie_read_dma_reg(reg) \
		do_read_volatile(PFO_DMA_CAP_REG_BASE_ADDR + DW_PCIE_DBI_BASE + (reg))

#define dw_pcie_write_dma_reg(reg, val) \
		do_write(PFO_DMA_CAP_REG_BASE_ADDR + DW_PCIE_DBI_BASE + (reg), val)
       // *((volatile uint32_t *)(PFO_DMA_CAP_REG_BASE_ADDR + DW_PCIE_DBI_BASE + (reg))) = (val)

#define dw_pcie_read_rdma_status(reg) \
		dw_pcie_read_dma_reg(DW_PCIE_RDMA_STATUS_OFF + (reg))

#define dw_pcie_write_rdma_status(reg, val) \
		dw_pcie_write_dma_reg(DW_PCIE_RDMA_STATUS_OFF + (reg), val)

#define dw_pcie_read_wdma_status(reg) \
		dw_pcie_read_dma_reg(DW_PCIE_WDMA_STATUS_OFF + (reg))

#define dw_pcie_write_wdma_status(reg, val) \
		dw_pcie_write_dma_reg(DW_PCIE_WDMA_STATUS_OFF + (reg), val)	

#define dw_pcie_read_rdma_ch(ch, reg) \
		dw_pcie_read_dma_reg(DW_PCIE_RDMA_CH_REG_OFF(ch) + (reg))

#define dw_pcie_write_rdma_ch(ch, reg, val) \
   		dw_pcie_write_dma_reg(DW_PCIE_RDMA_CH_REG_OFF(ch) + (reg), val)

#define dw_pcie_read_wdma_ch(ch, reg) \
    	dw_pcie_read_dma_reg(DW_PCIE_WDMA_CH_REG_OFF(ch) + (reg))

#define dw_pcie_write_wdma_ch(ch, reg, val) \
    	dw_pcie_write_dma_reg(DW_PCIE_WDMA_CH_REG_OFF(ch) + (reg), val)

#define dw_pcie_read_rdma_ctrl(reg) \
		dw_pcie_read_dma_reg(DW_PCIE_DMA_CTRL_OFF + DW_PCIE_RDMA_CTRL_REG_OFF(reg))
				
#define dw_pcie_write_rdma_ctrl(reg, val) \
		dw_pcie_write_dma_reg(DW_PCIE_DMA_CTRL_OFF + DW_PCIE_RDMA_CTRL_REG_OFF(reg), val)
		
#define dw_pcie_read_wdma_ctrl(reg) \
		dw_pcie_read_dma_reg(DW_PCIE_DMA_CTRL_OFF + DW_PCIE_WDMA_CTRL_REG_OFF(reg))

#define dw_pcie_write_wdma_ctrl(reg, val) \
    	dw_pcie_write_dma_reg(DW_PCIE_DMA_CTRL_OFF + DW_PCIE_WDMA_CTRL_REG_OFF(reg), val)

#define LOOPMAXTIMES     5  //防止死循环，必须得有退出机制

typedef uint64_t local_addr_t;
typedef uint64_t pcie_addr_t;


/****************DMA Write REG **********************************************************************/
typedef union {
	uint32_t v;
	struct
	{
		uint32_t DMA_WRITE_ENGINE : 1;                     // [0]	
		uint32_t RSVDP_1 : 15;                             // [15:1]
		uint32_t DMA_WRITE_ENGINE_EN_HSHAKE_CH0 : 1;       // [16]
		uint32_t DMA_WRITE_ENGINE_EN_HSHAKE_CH1 : 1;       // [17]
		uint32_t DMA_WRITE_ENGINE_EN_HSHAKE_CH2 : 1;       // [18]	
		uint32_t DMA_WRITE_ENGINE_EN_HSHAKE_CH3 : 1;       // [19]		
		uint32_t DMA_WRITE_ENGINE_EN_HSHAKE_CH4 : 1;       // [20]
		uint32_t DMA_WRITE_ENGINE_EN_HSHAKE_CH5 : 1;       // [21]
		uint32_t DMA_WRITE_ENGINE_EN_HSHAKE_CH6 : 1;       // [22]
		uint32_t DMA_WRITE_ENGINE_EN_HSHAKE_CH7 : 1;       // [23]
		uint32_t RSVDP_24 : 8;                             // [24:31]
	} b;
}DMA_WRITE_ENGINE_EN_REG_T;

//0x8421   1000010000100001
typedef union {
	uint32_t v;
	struct
	{
		uint32_t WRITE_CHANNEL0_WEIGHT : 5;                     // [4:0]	
		uint32_t WRITE_CHANNEL1_WEIGHT : 5;                     // [9:5]
		uint32_t WRITE_CHANNEL2_WEIGHT : 5;                     // [14:10]
		uint32_t WRITE_CHANNEL3_WEIGHT : 5;                     // [19:15]
		uint32_t RSVDP_20 : 12;                                  // [31:20]	
	} b;
}DMA_WRITE_CHANNEL_ARB_WEIGHT_LOW_REG_T;

//0x843F   1000010000111111
typedef union {
	uint32_t v;
	struct
	{
		uint32_t WRITE_CHANNEL4_WEIGHT : 5;                     // [4:0]	
		uint32_t WRITE_CHANNEL5_WEIGHT : 5;                     // [9:5]
		uint32_t WRITE_CHANNEL6_WEIGHT : 5;                     // [14:10]
		uint32_t WRITE_CHANNEL7_WEIGHT : 5;                     // [19:15]
		uint32_t RSVDP_20 : 12;                                  // [31:20]	
	} b;
}DMA_WRITE_CHANNEL_ARB_WEIGHT_HIGH_REG_T;

typedef union {
	uint32_t v;
	struct
	{
		uint32_t WR_CHANNEL_LLRAIE : 8;           // [7:0]	
		uint32_t RSVDP_8 : 8;                     // [15:8]
		uint32_t WR_CHANNEL_LLLAIE : 8;           // [23:16]
		uint32_t RSVDP_24 : 8;                    // [31:24]
	} b;
}DMA_WRITE_LINKED_LIST_ERR_EN_REG_T;

typedef union {
	uint32_t v;
	struct
	{
		uint32_t WR_DONE_INT_MASK : 8;           // [7:0]	
		uint32_t RSVDP_8 : 8;                     // [15:8]
		uint32_t WR_ABORT_INT_MASK : 8;           // [23:16]
		uint32_t RSVDP_24 : 8;                    // [31:24]
	} b;
}DMA_WRITE_INT_MASK_REG_T;

//0x308  1100001000
typedef union {
	uint32_t v;
	struct
	{
		uint32_t CB : 1;             // [0]	
		uint32_t TCB : 1;            // [1]
		uint32_t LLP : 1;            // [2]
		uint32_t LIE : 1;            // [3]
		uint32_t RIE : 1;            // [4]	
		uint32_t CS : 2;             // [6:5]
		uint32_t DMA_RESERVED0 : 1;  // [7]		
		uint32_t CCS : 1;            // [8]
		uint32_t LLE : 1;            // [9]
		uint32_t DMA_RESERVED1 : 2;  // [11:10]
		uint32_t DMA_FUNC_NUM : 2;   // [16:12]
		uint32_t DMA_RESERVED2 : 2;  // [22:17]
		uint32_t DMA_NS_DST : 1;     // [23]	
		uint32_t DMA_NS_SRC : 1;     // [24]
		uint32_t DMA_RO : 1;         // [25]
		uint32_t DMA_RESERVED5 : 1;  // [26]
		uint32_t DMA_TC : 2;         // [29:27]	
		uint32_t DMA_AT : 2;         // [31:30]		                            // [24:31]
	} b;
}DMA_CH_CONTROL1_OFF_WRCH_0_REG_T;


/****************DMA READ REG **********************************************************************/
typedef union {
	uint32_t v;
	struct
	{
		uint32_t DMA_READ_ENGINE : 1;                     // [0]	
		uint32_t RSVDP_1 : 15;                             // [15:1]
		uint32_t DMA_READ_ENGINE_EN_HSHAKE_CH0 : 1;       // [16]
		uint32_t DMA_READ_ENGINE_EN_HSHAKE_CH1 : 1;       // [17]
		uint32_t DMA_READ_ENGINE_EN_HSHAKE_CH2 : 1;       // [18]	
		uint32_t DMA_READ_ENGINE_EN_HSHAKE_CH3 : 1;       // [19]		
		uint32_t DMA_READ_ENGINE_EN_HSHAKE_CH4 : 1;       // [20]
		uint32_t DMA_READ_ENGINE_EN_HSHAKE_CH5 : 1;       // [21]
		uint32_t DMA_READ_ENGINE_EN_HSHAKE_CH6 : 1;       // [22]
		uint32_t DMA_READ_ENGINE_EN_HSHAKE_CH7 : 1;       // [23]
		uint32_t RSVDP_24 : 8;                             // [24:31]
	} b;
}DMA_READ_ENGINE_EN_REG_T;

//0x8421   1000010000100001
typedef union {
	uint32_t v;
	struct
	{
		uint32_t READ_CHANNEL0_WEIGHT : 5;                     // [4:0]	
		uint32_t READ_CHANNEL1_WEIGHT : 5;                     // [9:5]
		uint32_t READ_CHANNEL2_WEIGHT : 5;                     // [14:10]
		uint32_t READ_CHANNEL3_WEIGHT : 5;                     // [19:15]
		uint32_t RSVDP_20 : 12;                                  // [31:20]	
	} b;
}DMA_READ_CHANNEL_ARB_WEIGHT_LOW_REG_T;

//0x843F   1000010000111111
typedef union {
	uint32_t v;
	struct
	{
		uint32_t READ_CHANNEL4_WEIGHT : 5;                     // [4:0]	
		uint32_t READ_CHANNEL5_WEIGHT : 5;                     // [9:5]
		uint32_t READ_CHANNEL6_WEIGHT : 5;                     // [14:10]
		uint32_t READ_CHANNEL7_WEIGHT : 5;                     // [19:15]
		uint32_t RSVDP_20 : 12;                                  // [31:20]	
	} b;
}DMA_READ_CHANNEL_ARB_WEIGHT_HIGH_REG_T;

typedef union {
	uint32_t v;
	struct
	{
		uint32_t RD_CHANNEL_LLRAIE : 8;           // [7:0]	
		uint32_t RSVDP_8 : 8;                     // [15:8]
		uint32_t RD_CHANNEL_LLLAIE : 8;           // [23:16]
		uint32_t RSVDP_24 : 8;                    // [31:24]
	} b;
}DMA_READ_LINKED_LIST_ERR_EN_REG_T;

typedef union {
	uint32_t v;
	struct
	{
		uint32_t RD_DONE_INT_MASK : 8;           // [7:0]	
		uint32_t RSVDP_8 : 8;                     // [15:8]
		uint32_t RD_ABORT_INT_MASK : 8;           // [23:16]
		uint32_t RSVDP_24 : 8;                    // [31:24]
	} b;
}DMA_READ_INT_MASK_REG_T;

//0x308  1100001000
typedef union {
	uint32_t v;
	struct
	{
		uint32_t CB : 1;             // [0]	
		uint32_t TCB : 1;            // [1]
		uint32_t LLP : 1;            // [2]
		uint32_t LIE : 1;            // [3]
		uint32_t RIE : 1;            // [4]	
		uint32_t CS : 2;             // [6:5]
		uint32_t DMA_RESERVED0 : 1;  // [7]		
		uint32_t CCS : 1;            // [8]
		uint32_t LLE : 1;            // [9]
		uint32_t DMA_RESERVED1 : 2;  // [11:10]
		uint32_t DMA_FUNC_NUM : 2;   // [16:12]
		uint32_t DMA_RESERVED2 : 2;  // [22:17]
		uint32_t DMA_NS_DST : 1;     // [23]	
		uint32_t DMA_NS_SRC : 1;     // [24]
		uint32_t DMA_RO : 1;         // [25]
		uint32_t DMA_RESERVED5 : 1;  // [26]
		uint32_t DMA_TC : 2;         // [29:27]	
		uint32_t DMA_AT : 2;         // [31:30]		                            // [24:31]
	} b;
}DMA_CH_CONTROL1_OFF_RD_0_REG_T;

/********************************************************************************************************************/





typedef struct tDwPcieDmaLinkListNode {
    uint32_t flags;
    uint32_t size;
    uint64_t src_addr;
    uint64_t dst_addr;
} DwPcieDmaLinkListNode_t;

typedef struct tPcieDmaBuffer {
    void* buffer;
    void* bufByPcie;
    uint32_t size;
    uint32_t used;
} PcieDmaBuffer_t;

typedef struct tDwPcieEpDmaChDesc {
    PcieDmaBuffer_t* ll;
    local_addr_t cpu_addr;
    pcie_addr_t pci_addr;
    local_addr_t size;
    uint32_t local_irq_en;
    uint32_t remote_irq_en;
    uint16_t msg_data;
    uint32_t flags;
} DwPcieEpDmaChDesc_t;

typedef enum eDwPcieDmaChStatus {
  DW_PCIE_DMA_CH_DIS,
  DW_PCIE_DMA_CH_RUNNING,
  DW_PCIE_DMA_CH_HALTED,
  DW_PCIE_DMA_CH_STOPPED,
}DwPcieDmaChStatus_e;

int32_t ucp_pcie_dma_chain_desc_init(PcieDmaBuffer_t* buffer, uint32_t length);
int32_t ucp_pcie_rdma_chain_desc_fill(PcieDmaBuffer_t* buffer, uint32_t idx,local_addr_t cpu_addr, pcie_addr_t pci_addr, uint32_t size);
int32_t ucp_pcie_wdma_chain_desc_fill(PcieDmaBuffer_t* buffer, uint32_t idx,local_addr_t cpu_addr, pcie_addr_t pci_addr, uint32_t size);
int32_t ucp_pcie_rdma_chain_start(uint8_t ch, DwPcieEpDmaChDesc_t* desc);
int32_t ucp_pcie_wdma_chain_start(uint8_t ch, DwPcieEpDmaChDesc_t* desc);

//interrupt info
//#define DMA_PIC_INT_NUM 31
#define DMA_PIC_INT_NUM 511
//#define DMA_PIC_INT_NUM 466
//#define DMA_PIC_INT_NUM 18

#define PCIE_PIC_BASE 0x091e4000
#define PCIE_PIC_INTR_OFFSET (4*0)
#define PCIE_EDMA_INTR_OFFSET (4*7)

//#define dw_pcie_read_dma_int_reg(reg) (*((volatile uint32_t *)(PCIE_PIC_BASE +  reg)))
#define dw_pcie_read_dma_int_reg(reg) do_read_volatile(PCIE_PIC_BASE +  reg)

typedef int32_t (*dw_pcie_local_int_handler)(uint8_t ch);
typedef void (*irq_handler)();//maybe defined in smartOS.h

typedef struct tDwPcieEpDma {
    uint8_t num_channels;
    //uint32_t ch_map;	
    uint32_t ch_map[MAX_CH_NUM_DW_DMA];
    uint32_t irq_vec;
    dw_pcie_local_int_handler local_int_handler;
} DwPcieEpDma_t;

//bar1空间信息
typedef struct tEpBarInfo {	
    uint32_t number; //bar空间的编号
    uint32_t size; //bar空间的大小
	uint32_t phy_addr;//bar空间的地址
	uint32_t vir_addr;
	uint32_t addr_type;//地址类型，32位或者64位
	uint32_t mem_tpye; //bar类型，是memory或者IO
} EpBarInfo_t;

//bar nomber 定义
enum pci_barno
{
	BAR_0,
	BAR_1,
	BAR_2,
	BAR_3,
	BAR_4,
	BAR_5,
};

typedef struct tDwPcieEp {
    //uint8_t bar_to_ib;
    //void* mapped_bars;	
    DwPcieEpDma_t rdma;
    DwPcieEpDma_t wdma;	
	//add by gyl, bar1的相关信息
	EpBarInfo_t   bar[6];
	unsigned char ib_window_map[64];//atu 使用的位图，一共可以配置从0~256个atu区域
	unsigned char ob_window_map[64];//atu 使用的位图，一共可以配置从0~256个atu区域
	uint32_t num_ib_window;
	uint32_t num_ob_window;
} DwPcieEp_t;


//ATU
#define PCIE_ATU_MIN_REGION_SIZE (64*1024)
#define MAX_MEM_BAR_SIZE PCIE_ATU_MIN_REGION_SIZE

#define PCIE_OK 0
#define PCIE_EINVAL 1
#define PCIE_EBUSY 2
#define PCIE_EABORT 3

void pcie_ep_drv_init(void);
DwPcieEp_t* get_pcie_ep_dev(void);
uint32_t dw_pcie_dma_busy(DwPcieEpDma_t* dma, uint8_t ch);
void pcie_ep_dma_recfg(void);


#endif
