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 Wed Dec 02 10:36:49 2009 +1000 (14 years ago)
permissions -rw-r--r--
last change Add missing SUBV instruction to the emulation core (translation core is ok),
along with test cases. Thanks to D. Jeff Dionne for pointing this out.
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 }
.