Search
lxdream.org :: lxdream/test/dmac.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/dmac.c
changeset 561:533f6b478071
prev190:f7653df5e832
next753:1fe39c3a9bbc
author nkeynes
date Thu Jan 31 09:35:01 2008 +0000 (12 years ago)
permissions -rw-r--r--
last change Update release notes for 0.8.3
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 "dma.h"
    20 #include "asic.h"
    22 #define DMA_BASE 0xFFA00000
    24 #define DMA_SAR(c) (DMA_BASE+0x00+(c<<4))
    25 #define DMA_DAR(c) (DMA_BASE+0x04+(c<<4))
    26 #define DMA_TCR(c) (DMA_BASE+0x08+(c<<4))
    27 #define DMA_CHCR(c) (DMA_BASE+0x0C+(c<<4))
    28 #define DMA_OR (DMA_BASE+0x40)
    30 #define ASIC_BASE 0xA05F6000
    31 #define PVR_DMA_DEST  (ASIC_BASE+0x800)
    32 #define PVR_DMA_COUNT (ASIC_BASE+0x804)
    33 #define PVR_DMA_CTL   (ASIC_BASE+0x808)
    34 #define PVR_DMA_REGION (ASIC_BASE+0x884)
    36 void dmac_dump_channel( FILE *f, unsigned int channel )
    37 {
    38     fprintf( f, "DMAC SAR: %08X  Count: %08X  Ctl: %08X  OR: %08X\n",
    39 	     long_read(DMA_SAR(channel)), long_read(DMA_TCR(channel)), 
    40 	     long_read(DMA_CHCR(channel)), long_read(DMA_OR) );
    41 }
    44 /**
    45  * Setup the DMAC for a transfer. Assumes 32-byte block transfer.
    46  * Caller is responsible for making sure no-one else is using the
    47  * channel already. 
    48  *
    49  * @param channel DMA channel to use, 0 to 3
    50  * @param source source address (if a memory source)
    51  * @param dest   destination address (if a memory destination)
    52  * @param length number of bytes to transfer (must be a multiple of
    53  *               32.
    54  * @param direction 0 = host to device, 1 = device to host
    55  */
    56 void dmac_prepare_channel( int channel, uint32_t source, uint32_t dest,
    57 			   uint32_t length, int direction )
    58 {
    59     uint32_t control;
    61     if( direction == 0 ) {
    62 	/* DMA Disabled, IRQ disabled, 32 byte transfer, burst mode,
    63 	 * Memory => Device, Source addr increment, dest addr fixed
    64 	 */
    65 	control = 0x000012C0;
    66     } else {
    67 	/* DMA Disabled, IRQ disabled, 32 byte transfer, burst mode,
    68 	 * Device => Memory, Source addr fixed, dest addr increment
    69 	 */
    70 	control = 0x000043C0;
    71     }
    72     long_write( DMA_CHCR(channel), control );
    73     long_write( DMA_SAR(channel), source );
    74     long_write( DMA_DAR(channel), dest );
    75     long_write( DMA_TCR(channel), (length >> 5) );
    76     control |= 0x0001;
    77     long_write( DMA_CHCR(channel), control ); /* Enable DMA channel */
    78     long_write( DMA_OR, 0x8201 ); /* Ensure the DMAC config is set */
    79 }
    82 int pvr_dma_write( unsigned int target, char *buf, int len, int region )
    83 {
    84     uint32_t addr =(uint32_t)buf;
    85     int result;
    86     if( (addr & 0xFFFFFFE0) != addr ) {
    87 	fprintf( stderr, "Address error: Attempting DMA from %08X\n", addr );
    88 	return -1;
    89     }
    90     long_write( PVR_DMA_CTL, 0 ); /* Stop PVR dma if it's already running */
    91     asic_clear();
    93     dmac_prepare_channel( 2, (uint32_t)buf, 0, len, 0 ); /* Allocate channel 2 */
    94     long_write( PVR_DMA_DEST, target );
    95     long_write( PVR_DMA_COUNT, len );
    96     long_write( PVR_DMA_REGION, region );
    98     CHECK_IEQUALS( target, long_read(PVR_DMA_DEST) );
    99     CHECK_IEQUALS( len, long_read(PVR_DMA_COUNT) );
   100     CHECK_IEQUALS( 0, long_read(PVR_DMA_REGION) );
   101     CHECK_IEQUALS( (uint32_t)buf, long_read(DMA_SAR(2)) );
   102     CHECK_IEQUALS( len/32, long_read(DMA_TCR(2)) );
   103     CHECK_IEQUALS( 0x12C1, long_read(DMA_CHCR(2)) );
   105     long_write( PVR_DMA_CTL, 1 );
   106     result = asic_wait(EVENT_PVR_DMA);
   108     if( result != 0 ) {
   109 	fprintf( stderr, "PVR DMA failed (timeout)\n" );
   110 	asic_dump(stderr);
   111 	fprintf( stderr, "Dest: %08X  Count: %08X  Ctl: %08X\n", long_read(PVR_DMA_DEST),
   112 		 long_read(PVR_DMA_COUNT), long_read(PVR_DMA_CTL) );
   113 	dmac_dump_channel(stderr, 2);
   114 	long_write( PVR_DMA_CTL, 0 );
   115     }
   117     CHECK_IEQUALS( 0, long_read(PVR_DMA_CTL) );
   118     CHECK_IEQUALS( ((uint32_t)buf)+len, long_read(DMA_SAR(2))  );
   119     CHECK_IEQUALS( 0, long_read(DMA_TCR(2)) );
   120     CHECK_IEQUALS( 0x12C3, long_read(DMA_CHCR(2)) );
   121     CHECK_IEQUALS( target, long_read(PVR_DMA_DEST) );
   122     CHECK_IEQUALS( 0, long_read(PVR_DMA_COUNT) );
   123     CHECK_IEQUALS( 0, long_read(PVR_DMA_REGION) );
   125     return result;
   126 }
.