/**
 * PCieに関するH/Wイニシャル関連処理
 */

#include <string.h>
#include <ti/sysbios/family/arm/a15/Mmu.h>

#include <ti/sysbios/family/arm/a15/Cache.h>
#include <ti/sdo/edma3/rm/edma3_common.h>
#include <ti/drv/uart/UART_stdio.h>

#include "pcieHostInterface.h"

// ------ 後方参照 ------------
static void cache_writeback(void*, int);

/**
 * PCIeに関連するMMEの設定を行う。
 */
void pcieMmuInitial(void) {
    Mmu_DescriptorAttrs attrs;

    extern char ti_sysbios_family_arm_a15_Mmu_Module_State_0_secondLevelTableBuf_0__A;
    extern char ti_sysbios_family_arm_a15_Mmu_Module_State_0_secondLevelTableBuf_1__A;
    uint32_t addr0 = (uint32_t)&ti_sysbios_family_arm_a15_Mmu_Module_State_0_secondLevelTableBuf_0__A;
    uint32_t addr1 = (uint32_t)&ti_sysbios_family_arm_a15_Mmu_Module_State_0_secondLevelTableBuf_1__A;

    Mmu_initDescAttrs(&attrs);

    attrs.type = Mmu_DescriptorType_TABLE;
    attrs.shareable = 0;            // non-shareable
    attrs.accPerm = 1;              // read/write at any privelege level
    attrs.attrIndx = 0;             // Use MAIR0 Register Byte 3 for
                                    // determining the memory attributes
                                    // for each MMU entry

    // Update the first level table's MMU entry for 0x00000000 with the
    // new attributes.
    Mmu_setFirstLevelDesc((Ptr)0x00000000, (UInt64)addr0, &attrs);
    // Update the first level table's MMU entry for 0x40000000 with the
    // new attributes.
    Mmu_setFirstLevelDesc((Ptr)0x40000000, (UInt64)addr1, &attrs);
}

/**
 * PCIe関連レジスタ設定とホストとのデータ参照用メモリ空間の初期化を行う。
 *
 * */
void PcieRegisterInitial() {

    // ホストよりinbound参照されるメモリ空間をクリア
    // inboundデータエリアのアドレスを設定（モジュールでの未使用エリアを絶対アドレスで使用する）
    inbound_buf_t* inboudPtr = (inbound_buf_t*)INBOUND_DARA_ADDR;
    // inboundエリアをクリア
    memset((void*)inboudPtr, 0x00, sizeof(inbound_buf_t));
    cache_writeback ((void *)inboudPtr, sizeof(inbound_buf_t));

    EDMA3_DRV_Handle hEdma = NULL;
    hEdma = edmaInit(hEdma);
    if (hEdma==NULL) UART_printf("ERROR: EDMA handle not initialized!\n");
}

/**
 * キャッシュライトバック処理
 */
void cache_writeback (void *ptr, int size) {
    Cache_wb (ptr, size, Cache_Type_ALLD, TRUE);
}
