ajout channel 1 et 2 du Direct Memory Access Controller #1
|
@ -15,37 +15,46 @@
|
|||
// Driver interface
|
||||
//---
|
||||
|
||||
/* dma_get_channel_address()- returns address of the specified DMA channel */
|
||||
static sh7305_dma_channel_t *dma_get_channel_address(int num=0)
|
||||
{return (void*)(0xfe008020+16*x);}
|
||||
|
||||
|
||||
/* dma_setup() - Setup the DMA in interrupt or no-interrupt mode.
|
||||
The first parameters are as for dma_transfer() and dma_transfer_noint(). The
|
||||
last parameter indicates whether interrupts should be used.
|
||||
Returns non-zero if the DMA is busy or a configuration error occurs. */
|
||||
|
||||
|
||||
static int dma_setup(dma_size_t size, uint blocks,
|
||||
void *src, dma_address_t src_mode,
|
||||
void *dst, dma_address_t dst_mode,
|
||||
int interrupts)
|
||||
int interrupts,
|
||||
int channel=0)
|
||||
{
|
||||
sh7305_dma_channel_t* used_dma= dma_get_channel_address(channel);
|
||||
/* Safety guard: only start a transfer if there's not one running */
|
||||
if(DMA.DMA0.CHCR.DE) return 1;
|
||||
if(used_dma->CHCR.DE) return 1;
|
||||
|
||||
/* Disable DMA0 and disable the master DMA switch */
|
||||
DMA.DMA0.CHCR.DE = 0;
|
||||
used_dma->CHCR.DE = 0;
|
||||
DMA.OR.DME = 0;
|
||||
|
||||
/* Set DMA source and target address */
|
||||
DMA.DMA0.SAR = (uint32_t)src & 0x1fffffff;
|
||||
DMA.DMA0.DAR = (uint32_t)dst & 0x1fffffff;
|
||||
used_dma->SAR = (uint32_t)src & 0x1fffffff;
|
||||
used_dma->DAR = (uint32_t)dst & 0x1fffffff;
|
||||
|
||||
/* Set the number of blocks to be transferred */
|
||||
DMA.DMA0.TCR = blocks;
|
||||
used_dma->TCR = blocks;
|
||||
|
||||
/* Fill in CHCR. Set RS=0100 (auto-request) and the user-provided
|
||||
values for TS (transfer size), DM and SM (address modes) */
|
||||
DMA.DMA0.CHCR.lword = 0x00000400;
|
||||
DMA.DMA0.CHCR.TS_32 = (size >> 2);
|
||||
DMA.DMA0.CHCR.TS_10 = (size & 3);
|
||||
DMA.DMA0.CHCR.DM = dst_mode;
|
||||
DMA.DMA0.CHCR.SM = src_mode;
|
||||
DMA.DMA0.CHCR.IE = !!interrupts;
|
||||
used_dma->CHCR.lword = 0x00000400;
|
||||
used_dma->CHCR.TS_32 = (size >> 2);
|
||||
used_dma->CHCR.TS_10 = (size & 3);
|
||||
used_dma->CHCR.DM = dst_mode;
|
||||
used_dma->CHCR.SM = src_mode;
|
||||
used_dma->CHCR.IE = !!interrupts;
|
||||
|
||||
/* Prepare DMAOR by enabling the master switch and clearing the
|
||||
blocking flags. */
|
||||
|
@ -59,38 +68,42 @@ static int dma_setup(dma_size_t size, uint blocks,
|
|||
/* dma_transfer() - Perform a data transfer */
|
||||
void dma_transfer(dma_size_t size, uint blocks,
|
||||
void *src, dma_address_t src_mode,
|
||||
void *dst, dma_address_t dst_mode)
|
||||
void *dst, dma_address_t dst_mode,
|
||||
int channel=0)
|
||||
{
|
||||
if(dma_setup(size, blocks, src, src_mode, dst, dst_mode, 1)) return;
|
||||
sh7305_dma_channel_t* used_dma=dma_get_channel_address(channel);
|
||||
if(dma_setup(size, blocks, src, src_mode, dst, dst_mode, 1, channel)) return;
|
||||
|
||||
/* Enable channel 0, starting the DMA transfer. */
|
||||
DMA.DMA0.CHCR.DE = 1;
|
||||
used_dma->CHCR.DE = 1;
|
||||
}
|
||||
|
||||
/* dma_transfer_wait() - Wait for a transfer on channel 0 to finish */
|
||||
void dma_transfer_wait(void)
|
||||
void dma_transfer_wait(int channel=0)
|
||||
{
|
||||
/* The master switch is cut when the transfer ends */
|
||||
while(DMA.OR.DME) sleep();
|
||||
while(DMA.OR.DME) sleep(); // i think we can replace it by while(used_dma->CHCR.DE)
|
||||
}
|
||||
|
||||
/* dma_transfer_noint() - Perform a data transfer without interruptions */
|
||||
void dma_transfer_noint(dma_size_t size, uint blocks,
|
||||
void *src, dma_address_t src_mode,
|
||||
void *dst, dma_address_t dst_mode)
|
||||
void *dst, dma_address_t dst_mode,
|
||||
int channel=0)
|
||||
{
|
||||
if(dma_setup(size, blocks, src, src_mode, dst, dst_mode, 0)) return;
|
||||
sh7305_dma_channel_t* used_dma=dma_get_channel_address(channel);
|
||||
if(dma_setup(size, blocks, src, src_mode, dst, dst_mode, 0,channel)) return;
|
||||
|
||||
/* Enable channel 0, starting the DMA transfer. */
|
||||
DMA.DMA0.CHCR.DE = 1;
|
||||
used_dma->CHCR.DE = 1;
|
||||
|
||||
/* Actively wait until the transfer is finished */
|
||||
while(!DMA.DMA0.CHCR.TE);
|
||||
while(!used_dma->CHCR.TE);
|
||||
|
||||
/* Disable the channel and clear the TE flag. Disable the channel first
|
||||
as clearing the TE flag will allow the transfer to restart */
|
||||
DMA.DMA0.CHCR.DE = 0;
|
||||
DMA.DMA0.CHCR.TE = 0;
|
||||
used_dma->CHCR.DE = 0;
|
||||
used_dma->CHCR.TE = 0;
|
||||
|
||||
/* Clear the AE and NMIF status flags and cut the master switch */
|
||||
DMA.OR.DME = 0;
|
||||
|
@ -107,11 +120,9 @@ static void init(void)
|
|||
/* This driver is not implemented on SH3 */
|
||||
if(isSH3()) return;
|
||||
|
||||
/* Install the interrupt handler from dma/inth.s */
|
||||
/* Install the interrupt handler from dma/inth.s and set priority to 3*/
|
||||
extern void inth_dma_dma0(void);
|
||||
gint_inthandler(0x800, inth_dma_dma0, 32);
|
||||
|
||||
/* Set interrupt priority to 3 */
|
||||
gint_intlevel(16, 3);
|
||||
|
||||
/* Unmask the DMA0 interrupt */
|
||||
|
|
|
@ -3,30 +3,77 @@
|
|||
** An easy one, just clears some flags and marks all transfers as finished.
|
||||
*/
|
||||
|
||||
.global _inth_dma_dma0
|
||||
.section .gint.blocks, "ax"
|
||||
.align 4
|
||||
|
||||
/* DMA TRANSFER ENDED INTERRUPT HANDLER - BYTES */
|
||||
|
||||
|
||||
.global _inth_dma_dma0
|
||||
_inth_dma_dma0:
|
||||
/* Clear the TE flag and DMA Enable in CHCR */
|
||||
mov.l 1f, r1
|
||||
mov.l @r1, r0
|
||||
mov #-4, r2
|
||||
and r2, r0
|
||||
mov.l r0, @r1
|
||||
/* Clear the TE flag and DMA Enable in CHCR */
|
||||
mov.l 1f, r1
|
||||
mov.l @r1, r0
|
||||
mov #-4, r2
|
||||
and r2, r0
|
||||
mov.l r0, @r1
|
||||
|
||||
/* Clear the AE and NMIF flags in OR, and cut the master switch */
|
||||
add #0x34, r1
|
||||
mov.w @r1, r0
|
||||
shlr8 r0
|
||||
shll8 r0
|
||||
mov.w r0, @r1
|
||||
/* Clear the AE and NMIF flags in OR, and cut the master switch */
|
||||
add #0x34, r1
|
||||
mov.w @r1, r0
|
||||
shlr8 r0
|
||||
shll8 r0
|
||||
mov.w r0, @r1
|
||||
|
||||
rte
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
rte
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
1: .long 0xfe00802c /* CHCR0 - OR is 0x34 bytes after this */
|
||||
|
||||
|
||||
.global _inth_dma_dma1
|
||||
_inth_dma_dma1:
|
||||
/* Clear the TE flag and DMA Enable in CHCR */
|
||||
mov.l 2f, r1
|
||||
mov.l @r1, r0
|
||||
mov #-4, r2
|
||||
and r2, r0
|
||||
mov.l r0, @r1
|
||||
|
||||
/* Clear the AE and NMIF flags in OR, and cut the master switch */
|
||||
add #0x34, r1
|
||||
mov.w @r1, r0
|
||||
shlr8 r0
|
||||
shll8 r0
|
||||
mov.w r0, @r1
|
||||
|
||||
rte
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
|
||||
|
||||
.global _inth_dma_dma2
|
||||
_inth_dma_dma2:
|
||||
/* Clear the TE flag and DMA Enable in CHCR */
|
||||
mov.l 3f, r1
|
||||
mov.l @r1, r0
|
||||
mov #-4, r2
|
||||
and r2, r0
|
||||
mov.l r0, @r1
|
||||
|
||||
/* Clear the AE and NMIF flags in OR, and cut the master switch */
|
||||
add #0x34, r1
|
||||
mov.w @r1, r0
|
||||
shlr8 r0
|
||||
shll8 r0
|
||||
mov.w r0, @r1
|
||||
|
||||
rte
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
|
||||
1: .long 0xfe00802c /* CHCR0 - OR is 0x34 bytes after this */
|
||||
2: .long 0xfe00803c
|
||||
3: .long 0xfe00804c
|
Loading…
Reference in New Issue