#include "sdma.h" #define DMA_PACK_LNG 0x40000 const unsigned int minTransferSizeInBytes = 128; const unsigned int maxLoopIterations = 256; PSDMA_CB sdmaPtr = ((PSDMA_CB) SDMA_BASE); unsigned run_channel(unsigned int channel, unsigned int inst0, unsigned int pc) { int state = 0; int err = 0; if (sdmaPtr->dbgstatus != 0) { return 3; } sdmaPtr->dbginst0 = inst0; sdmaPtr->dbginst1 = pc; sdmaPtr->dbgcmd = 0x0; do { state = sdmaPtr->chCtrl[channel].csr & 0xf; if(state == 0) { break; } else { if (state != 0) { err = sdmaPtr->chCtrl[channel].csr & 0xf; } } } while(1); return sdmaPtr->dbgstatus; } void sdma_copy(int dma_id, unsigned int *dst, unsigned int *src, int size) { // Simple programm - transfer in one loop if ((dma_id < 0) || (dma_id > 7)) { return; // TODO: enum with error types } if (size <= 0) { return; // TODO: enum with error types } // setup codes of sdma-microprogram unsigned int prog_fast[] = {0xC2F701BC, 0x00BC00BD, 0x00000000, 0x02BC1818, 0x00000000, 0x08040020, 0x18000238}; unsigned int prog_slow[] = {0x420501BC, 0x00BC0081, 0x00000000, 0x02BC1818, 0x00000000, 0x08040020, 0x18000238}; int maxBlockSize = 0; int transfersNumber = 0; int reminder = 0; maxBlockSize = minTransferSizeInBytes * maxLoopIterations; // 8192 words transfersNumber = size/maxBlockSize; int i = 0; unsigned int dmago0 = 0xa0; dmago0 = (dma_id << 24) | (dmago0 << 16) | (dma_id << 8) | 0x0; //(0x00a00000); unsigned int* src1 = src; unsigned int* dst1 = dst; unsigned int dif = (maxBlockSize >> 2); // main loop for(i = 0; i < transfersNumber; i++) { prog_fast[2] = (unsigned int) (src1); prog_fast[4] = (unsigned int) (dst1); prog_fast[5] |= (unsigned int)((maxLoopIterations-1) << 8); run_channel(dma_id, dmago0, (unsigned int) prog_fast); src1 += dif; dst1 += dif; } reminder = size%maxBlockSize; if(reminder != 0) { int loop_iter = size/128; int rem = size%128; if (loop_iter >= 0) { prog_fast[2] = (unsigned int) (src1); prog_fast[4] = (unsigned int) (dst1); prog_fast[5] |= (unsigned int)((loop_iter - 1) << 8); run_channel(dma_id, dmago0, (unsigned int) prog_fast); } if(rem != 0) { rem = rem >> 2; rem--; prog_slow[2] = (unsigned int) (src1+loop_iter*32); prog_slow[4] = (unsigned int) (dst1+loop_iter*32); prog_slow[5] |= (unsigned int)(rem << 8); run_channel(dma_id, dmago0, (unsigned int) prog_slow); } } } void sdma_copy2d(int dma_id, unsigned int *dst, unsigned int stride_dst, unsigned int *src, unsigned int stride_src, int width, int height) { if ((dma_id < 0) || (dma_id > 7)) { return; // TODO: enum with error types } if (width <= 0) { return; } if (height <= 0) { return; } if ((stride_dst < width) || (stride_src < width)) { return; } /*if (stride_dst == 0) stride_dst = width; if (stride_src == 0) stride_src = width; */ // setup codes of sdma-microprogram unsigned int prog_fast[] = {0x420501BC, 0x00BC0081, 0x00000000, 0x02BC1818, 0x00000000, 0x00220020, 0x023C0804, 0x56000054, 0x0C380000, 0x18181800}; /* int maxBlockSize = minTransferSizeInBytes * maxLoopIterations; // 8192 words */ unsigned int dmago0 = 0xa0; dmago0 = (dma_id << 24) | (dmago0 << 16) | (dma_id << 8) | 0x0; //(0x00a00000); int loop_iter = width>>2; prog_fast[2] = (unsigned int) (src); prog_fast[4] = (unsigned int) (dst); prog_fast[5] |= (unsigned int)((loop_iter - 1) <<24); prog_fast[5] |= (unsigned int)((height - 1) << 8); prog_fast[7] |= (unsigned int)((stride_src - width) << 8); prog_fast[8] |= (unsigned int)(stride_dst - width); run_channel(dma_id, dmago0, (unsigned int) prog_fast); }