void ppuConfigEDMA( PPU_DevHandle device, Int channelnum) { Ptr dest; Ptr dest_lastframe; Int framesize; Int lastframesize; Int numframes; PPU_ChannelHandle chan; const PPU_PictureChannelHAL * hal; chan = &device->Channels[channelnum]; hal = &(ppuHal.PictureChannel[channelnum]); framesize = chan->Framesize; lastframesize = chan->LastFramesize; numframes = chan->NumFrames; //dbgLog("DMA set up on chan: %d. frame: %d, last: %d, num: %d", channelnum, framesize, lastframesize, numframes ); //dbgLog("Picsize: %d", chan->PicSize ); // Calculate the target pointers dest = (Ptr)( (Int)(chan->Buffer) + PIC_HEADERSIZE ); dest_lastframe = (Ptr)( (Int)dest + (numframes * framesize) ); // a macro which defines the OPT fields of the dma config. Its arguments define whether the DMA // will trigger a transfer completion interrupt, which tcc would be used for that interrupt and // if it is a linked DMA. #define PPU_EDMA_STDOPT(tcint, tcc, link) EDMA_OPT_RMK( 0x0, /* Priority: urgent! //high, but not urgent. */ \ 0x0, /* element size (16 bit) */ \ 0, /* 2D source */ \ 00, /* source update mode (Fixed address) */ \ 0x00, /* 2D dest */ \ 0x1, /* dest update mode */ \ tcint, /* Transfer complete interrupt flag (1=enable) */ \ (tcc & 0xF), /* Transfer complete code (4bits) */ \ ((tcc & 0x30) >> 4), /* Transfer complete code most significant bits (2bits, 64x only) */ \ 0, /* Alternate complete interrupt flag */ \ 0x00, /* Alternate transfer complete code */ \ 0, /* PDT source */ \ 0, /* PDT dest */ \ link, /* link */ \ 1 ) /* Frame synchronisation (0=element, 1=frame) */ // Check if the DMA transfer has to be split up because the framesize doesn't fit if (lastframesize == 0) { // no split up required EDMA_configArgs( chan->DMA1, PPU_EDMA_STDOPT(1, chan->TCC, 1), // Do interrupt, link to null table. EDMA_SRC_RMK(hal->pFifo), // Source Address EDMA_CNT_RMK(numframes-1, framesize/4), // Transfer Counter - Numeric EDMA_DST_RMK(dest), // Destination Address - Numeric EDMA_IDX_RMK(0,0), // Index register - Numeric EDMA_RLD_RMK(0, ppuDMANull) ); // No "Element Count Reload", but link to next DMA. } else if (numframes == 0) { // no split up (only the last frame needed.) EDMA_configArgs( chan->DMA1, PPU_EDMA_STDOPT(1, chan->TCC, 1), // Do interrupt, link to null table. EDMA_SRC_RMK(hal->pFifo), // Source Address EDMA_CNT_RMK(0, lastframesize/4), // Transfer Counter - Numeric EDMA_DST_RMK(dest_lastframe), // Destination Address - Numeric EDMA_IDX_RMK(0,0), // Index register - Numeric EDMA_RLD_RMK(0, ppuDMANull) ); // No "Element Count Reload", but link to next DMA. } else { // multiple frames, and a lastframe EDMA_configArgs( chan->DMA1, PPU_EDMA_STDOPT(0, chan->TCC, 1), // no interrupt, but link with next dma. EDMA_SRC_RMK(hal->pFifo), // Source Address EDMA_CNT_RMK(numframes-1, framesize/4), // Transfer Counter - Numeric EDMA_DST_RMK(dest), // Destination Address - Numeric EDMA_IDX_RMK(0,0), // Index register - Numeric EDMA_RLD_RMK(0, chan->DMA2) // No "Element Count Reload", but link to next DMA. ); EDMA_configArgs(chan->DMA2, PPU_EDMA_STDOPT(1, chan->TCC, 1), // Do generate an interrupt. EDMA_SRC_RMK(hal->pFifo), // Source Address EDMA_CNT_RMK(0, lastframesize/4), // Transfer Counter - Numeric EDMA_DST_RMK( dest_lastframe ), // Destination Address - Numeric EDMA_IDX_RMK(0,0), // Index register - Numeric EDMA_RLD_RMK(0, ppuDMANull) // No "Element Count Reload", but link to null DMA. ); } }
EDMA_OPT_RMK( EDMA_OPT_PRI_LOW, EDMA_OPT_ESIZE_32BIT, EDMA_OPT_2DS_NO, EDMA_OPT_SUM_NONE, // no source address update EDMA_OPT_2DD_NO, EDMA_OPT_DUM_INC, // increment destination address EDMA_OPT_TCINT_YES, // Source address update mode EDMA_OPT_TCC_DEFAULT, EDMA_OPT_LINK_YES, EDMA_OPT_FS_NO), // Frame synchronisation, we copy element by element EDMA_SRC_OF(0x00000000), // EDMA Channel Source Address EDMA_CNT_RMK(0, 108), // Frame count (FRMCNT), Element count (FRMCNT) EDMA_DST_OF((Uint32) &gRcvBufferA), // EDMA Channel Destination Address EDMA_IDX_RMK(EDMA_IDX_FRMIDX_DEFAULT, EDMA_IDX_ELEIDX_DEFAULT), // Frame index, Element index EDMA_RLD_RMK(0x0000, 0x0000) // Element count reload, Link address }; /* * EDMA transmit channel config */ EDMA_Config gEdmaXmtConfig = { EDMA_OPT_RMK( EDMA_OPT_PRI_LOW, EDMA_OPT_ESIZE_32BIT, EDMA_OPT_2DS_NO, EDMA_OPT_SUM_INC, // increment source address EDMA_OPT_2DD_NO, EDMA_OPT_DUM_NONE, // don't update destination (TDR) EDMA_OPT_TCINT_YES, // Source address update mode EDMA_OPT_TCC_DEFAULT,