Search
lxdream.org :: lxdream/test/dmac.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/dmac.c
changeset 815:866c103d72cd
prev812:8cc61d5ea1f8
author nkeynes
date Fri May 29 18:47:05 2015 +1000 (7 years ago)
permissions -rw-r--r--
last change Fix test case
view annotate diff log raw
     1 /**
     2  * $Id$
     3  * 
     4  * DMA support code
     5  *
     6  * Copyright (c) 2006 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #include <assert.h>
    20 #include "dma.h"
    21 #include "asic.h"
    23 #define DMA_BASE 0xFFA00000
    25 #define DMA_SAR(c) (DMA_BASE+0x00+(c<<4))
    26 #define DMA_DAR(c) (DMA_BASE+0x04+(c<<4))
    27 #define DMA_TCR(c) (DMA_BASE+0x08+(c<<4))
    28 #define DMA_CHCR(c) (DMA_BASE+0x0C+(c<<4))
    29 #define DMA_OR (DMA_BASE+0x40)
    31 #define ASIC_BASE 0xA05F6000
    32 #define PVR_DMA_DEST  (ASIC_BASE+0x800)
    33 #define PVR_DMA_COUNT (ASIC_BASE+0x804)
    34 #define PVR_DMA_CTL   (ASIC_BASE+0x808)
    35 #define PVR_DMA_REGION (ASIC_BASE+0x884)
    37 #define SORT_DMA_TABLE (ASIC_BASE+0x810)
    38 #define SORT_DMA_DATA  (ASIC_BASE+0x814)
    39 #define SORT_DMA_TABLEBITS (ASIC_BASE+0x818)
    40 #define SORT_DMA_DATASIZE (ASIC_BASE+0x81C)
    41 #define SORT_DMA_CTL   (ASIC_BASE+0x820)
    42 #define SORT_DMA_COUNT (ASIC_BASE+0x860)
    44 #define AICA_RAM_BASE 0xA0800000
    45 #define AICA_RAM_SIZE 0x00200000
    47 #define G2DMABASE 0xA05F7800
    48 #define G2DMATIMEOUT (G2DMABASE+0x90)
    49 #define G2DMAMAGIC (G2DMABASE+0xBC)
    50 #define G2DMAEXT(x) (G2DMABASE+(0x20*(x)))
    51 #define G2DMAHOST(x) (G2DMABASE+(0x20*(x))+0x04)
    52 #define G2DMASIZE(x) (G2DMABASE+(0x20*(x))+0x08)
    53 #define G2DMADIR(x) (G2DMABASE+(0x20*(x))+0x0C)
    54 #define G2DMAMODE(x) (G2DMABASE+(0x20*(x))+0x10)
    55 #define G2DMACTL1(x) (G2DMABASE+(0x20*(x))+0x14)
    56 #define G2DMACTL2(x) (G2DMABASE+(0x20*(x))+0x18)
    57 #define G2DMASTOP(x) (G2DMABASE+(0x20*(x))+0x1C)
    59 void dmac_dump_channel( FILE *f, unsigned int channel )
    60 {
    61     fprintf( f, "DMAC SAR: %08X  Count: %08X  Ctl: %08X  OR: %08X\n",
    62 	     long_read(DMA_SAR(channel)), long_read(DMA_TCR(channel)), 
    63 	     long_read(DMA_CHCR(channel)), long_read(DMA_OR) );
    64 }
    67 /**
    68  * Setup the DMAC for a transfer. Assumes 32-byte block transfer.
    69  * Caller is responsible for making sure no-one else is using the
    70  * channel already. 
    71  *
    72  * @param channel DMA channel to use, 0 to 3
    73  * @param source source address (if a memory source)
    74  * @param dest   destination address (if a memory destination)
    75  * @param length number of bytes to transfer (must be a multiple of
    76  *               32.
    77  * @param direction 0 = host to device, 1 = device to host
    78  */
    79 void dmac_prepare_channel( int channel, uint32_t source, uint32_t dest,
    80 			   uint32_t length, int direction )
    81 {
    82     uint32_t control;
    84     if( direction == 0 ) {
    85 	/* DMA Disabled, IRQ disabled, 32 byte transfer, burst mode,
    86 	 * Memory => Device, Source addr increment, dest addr fixed
    87 	 */
    88 	control = 0x000012C0;
    89     } else {
    90 	/* DMA Disabled, IRQ disabled, 32 byte transfer, burst mode,
    91 	 * Device => Memory, Source addr fixed, dest addr increment
    92 	 */
    93 	control = 0x000043C0;
    94     }
    95     long_write( DMA_CHCR(channel), control );
    96     long_write( DMA_SAR(channel), source );
    97     long_write( DMA_DAR(channel), dest );
    98     long_write( DMA_TCR(channel), (length >> 5) );
    99     control |= 0x0001;
   100     long_write( DMA_CHCR(channel), control ); /* Enable DMA channel */
   101     long_write( DMA_OR, 0x8201 ); /* Ensure the DMAC config is set */
   102 }
   105 int pvr_dma_write( unsigned int target, char *buf, int len, int region )
   106 {
   107     uint32_t addr =(uint32_t)buf;
   108     int result;
   109     if( (addr & 0xFFFFFFE0) != addr ) {
   110 	fprintf( stderr, "Address error: Attempting DMA from %08X\n", addr );
   111 	return -1;
   112     }
   113     long_write( PVR_DMA_CTL, 0 ); /* Stop PVR dma if it's already running */
   114     asic_clear();
   116     dmac_prepare_channel( 2, (uint32_t)buf, 0, len, 0 ); /* Allocate channel 2 */
   117     long_write( PVR_DMA_DEST, target );
   118     long_write( PVR_DMA_COUNT, len );
   119     long_write( PVR_DMA_REGION, region );
   121     CHECK_IEQUALS( target, long_read(PVR_DMA_DEST) );
   122     CHECK_IEQUALS( len, long_read(PVR_DMA_COUNT) );
   123     CHECK_IEQUALS( 0, long_read(PVR_DMA_REGION) );
   124     CHECK_IEQUALS( (uint32_t)buf, long_read(DMA_SAR(2)) );
   125     CHECK_IEQUALS( len/32, long_read(DMA_TCR(2)) );
   126     CHECK_IEQUALS( 0x12C1, long_read(DMA_CHCR(2)) );
   128     long_write( PVR_DMA_CTL, 1 );
   129     result = asic_wait(EVENT_PVR_DMA);
   131     if( result != 0 ) {
   132 	fprintf( stderr, "PVR DMA failed (timeout)\n" );
   133 	asic_dump(stderr);
   134 	fprintf( stderr, "Dest: %08X  Count: %08X  Ctl: %08X\n", long_read(PVR_DMA_DEST),
   135 		 long_read(PVR_DMA_COUNT), long_read(PVR_DMA_CTL) );
   136 	dmac_dump_channel(stderr, 2);
   137 	long_write( PVR_DMA_CTL, 0 );
   138     }
   140     CHECK_IEQUALS( 0, long_read(PVR_DMA_CTL) );
   141     CHECK_IEQUALS( ((uint32_t)buf)+len, long_read(DMA_SAR(2))  );
   142     CHECK_IEQUALS( 0, long_read(DMA_TCR(2)) );
   143     CHECK_IEQUALS( 0x12C3, long_read(DMA_CHCR(2)) );
   144     CHECK_IEQUALS( target, long_read(PVR_DMA_DEST) );
   145     CHECK_IEQUALS( 0, long_read(PVR_DMA_COUNT) );
   146     CHECK_IEQUALS( 0, long_read(PVR_DMA_REGION) );
   148     return result;
   149 }
   151 int sort_dma_write( char *sorttable, int tablelen, char *data, int datalen, int bitwidth, int datasize )
   152 {
   153     int result;
   154     uint32_t tableaddr = (uint32_t)sorttable;
   155     uint32_t dataaddr = (uint32_t)data;
   157     long_write( SORT_DMA_CTL, 0 );
   158     asic_clear();
   160     long_write( SORT_DMA_TABLE, tableaddr );
   161     long_write( SORT_DMA_DATA, dataaddr );
   162     long_write( SORT_DMA_TABLEBITS, bitwidth );
   163     long_write( SORT_DMA_DATASIZE, datasize );
   164     long_write( SORT_DMA_CTL, 1 );
   165     result = asic_wait2(EVENT_SORT_DMA, EVENT_SORT_DMA_ERR);
   166     if( result == -1 ) {
   167         fprintf( stderr, "SORT DMA failed (timeout)\n" );
   168         asic_dump(stderr);
   169         fprintf( stderr, "Table: %08X Count: %08X Ctl: %08X\n", long_read(SORT_DMA_TABLE), long_read(SORT_DMA_COUNT),
   170                  long_read(SORT_DMA_CTL) );
   171         long_write( SORT_DMA_CTL, 0 );
   172     }
   173     CHECK_IEQUALS( 0, long_read(SORT_DMA_CTL) );
   174     return result;
   175 }
   177 int aica_dma_transfer( uint32_t aica_addr, char *data, uint32_t size, int writeFlag )
   178 {
   179     long_write( G2DMATIMEOUT, 0 );
   180     long_write( G2DMAMAGIC, 0x4659404f );
   181     long_write( G2DMACTL1(0), 0 );
   182     long_write( G2DMAEXT(0), aica_addr );
   183     long_write( G2DMAHOST(0), ((uint32_t)data) );
   184     long_write( G2DMASIZE(0), ((size+31)&0x7FFFFFE0) | 0x80000000 );
   185     long_write( G2DMADIR(0), (writeFlag ? 0 : 1) );
   186     long_write( G2DMAMODE(0), 0 );
   188     long_write( G2DMACTL1(0), 1 );
   189     long_write( G2DMACTL2(0), 1 );
   190     if( asic_wait( EVENT_G2_DMA0 ) != 0 ) {
   191         fprintf( stderr, "Timeout waiting for G2 DMA event\n" );
   192         return -1;
   193     }
   194     // CHECK_IEQUALS( 0, long_read( G2DMACTL1(0) ) );
   195     CHECK_IEQUALS( 0, long_read( G2DMACTL2(0) ) );
   196     return 0;
   197 }
   199 int aica_dma_write( uint32_t aica_addr, char *data, uint32_t size )
   200 {
   201     return aica_dma_transfer( aica_addr, data, size, 1 );
   202 }
   204 int aica_dma_read( char *data, uint32_t aica_addr, uint32_t size )
   205 {
   206     return aica_dma_transfer( aica_addr, data, size, 0 );
   207 }
   209 int memcpy_to_aica( uint32_t aica_addr, void *data, size_t size )
   210 {
   211     assert( (aica_addr & 0x03) == 0 );
   212     uint32_t *src = (uint32_t *)data;
   213     uint32_t *dest = (uint32_t *)aica_addr;
   214     while( size > 0 ) {
   215         int i;
   216         if( g2_fifo_wait() != 0 ) {
   217             return -1;
   218         }
   219         irq_disable();
   220         for( i=0; i<8 && size > 0; i++ ) {
   221             *dest++ = *src++;
   222             size -= 4;
   223         }
   224         irq_enable();
   225     }
   226     return 0;
   227 }
.