// Copyright 2025 RnD Center "ELVEES", JSC

#ifndef DMAINIT_H
#define DMAINIT_H

#define DMA_STATS
#define USE_HAPS

#include <malloc.h>
#include <stdlib.h>

#include "elcore50-matrix-lib/elcore50.h"

// #define NODMA
#ifndef NODMA
#define vdma_busy(ich) ((*(volatile uint32 *)&VDMACtrl->ch[ich].csr & 0x82) != 0x02)
#define vdma_run(ich) *(volatile uint32 *)&VDMACtrl->ch[ich].csr = 8
#else
#define vdma_busy(ich) 0
#define vdma_run(ich)
#endif
#define vdma_wait(ich) while (vdma_busy(ich))

void initload(VDMAINIT *link, void *src, void *dst, int32 width, int32 height, int32 sstride, int32 dstride);
void initstore(VDMAINIT *link, void *src, void *dst, int32 width, int32 height, int32 sstride, int32 dstride);

typedef struct VDMABlock {
  struct VDMABlock *next;
  VDMAINIT *span;
  int32 total, used;
} VDMABlock;

typedef struct {
  VDMAINIT *nose;
  VDMABlock *tail;
} VDMAChain;

int32 initchain(VDMAChain *ch, int32 initcnt);
void destroychain(VDMAChain *ch);
int32 enqload(VDMAChain *ch, void *src, void *dst, int32 width, int32 height, int32 sstride, int32 dstride);
int32 enqstore(VDMAChain *ch, void *src, void *dst, int32 width, int32 height, int32 sstride, int32 dstride);
int32 enqbreak(VDMAChain *ch);
void armchain(VDMAChain *ch, int32 nch);
void startchain(VDMAChain *ch, int32 nch);
void waitchain(int32 nch);
void resumechain(int32 nch);

int32 enqload4d(VDMAChain *ch, void *src, void *dst, int32 channels, int32 width, int32 height, int32 batch,
                int32 sstride_width, int32 sstride_height, int32 sstride_batch, int32 dstride_width,
                int32 dstride_height, int32 dstride_batch);

int32 enqstore4d(VDMAChain *ch, void *src, void *dst, int32 channels, int32 width, int32 height, int32 batch,
                 int32 sstride_width, int32 sstride_height, int32 sstride_batch, int32 dstride_width,
                 int32 dstride_height, int32 dstride_batch);

#endif
