Search
lxdream.org :: lxdream/test/dmac.c :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename test/dmac.c
changeset 185:6755a04c447f
next190:f7653df5e832
author nkeynes
date Tue Jul 11 01:35:27 2006 +0000 (17 years ago)
permissions -rw-r--r--
last change First commit of system test framework. 3 initial test cases (incomplete):
testide, testmath, and testta
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/test/dmac.c Tue Jul 11 01:35:27 2006 +0000
1.3 @@ -0,0 +1,128 @@
1.4 +/**
1.5 + * $Id: dmac.c,v 1.1 2006-07-11 01:35:23 nkeynes Exp $
1.6 + *
1.7 + * DMA support code
1.8 + *
1.9 + * Copyright (c) 2006 Nathan Keynes.
1.10 + *
1.11 + * This program is free software; you can redistribute it and/or modify
1.12 + * it under the terms of the GNU General Public License as published by
1.13 + * the Free Software Foundation; either version 2 of the License, or
1.14 + * (at your option) any later version.
1.15 + *
1.16 + * This program is distributed in the hope that it will be useful,
1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.19 + * GNU General Public License for more details.
1.20 + */
1.21 +
1.22 +#include "dma.h"
1.23 +#include "asic.h"
1.24 +
1.25 +#define DMA_BASE 0xFFA00000
1.26 +
1.27 +#define DMA_SAR(c) (DMA_BASE+0x00+(c<<4))
1.28 +#define DMA_DAR(c) (DMA_BASE+0x04+(c<<4))
1.29 +#define DMA_TCR(c) (DMA_BASE+0x08+(c<<4))
1.30 +#define DMA_CHCR(c) (DMA_BASE+0x0C+(c<<4))
1.31 +#define DMA_OR (DMA_BASE+0x40)
1.32 +
1.33 +#define ASIC_BASE 0xA05F6000
1.34 +#define PVR_DMA_DEST (ASIC_BASE+0x800)
1.35 +#define PVR_DMA_COUNT (ASIC_BASE+0x804)
1.36 +#define PVR_DMA_CTL (ASIC_BASE+0x808)
1.37 +#define PVR_DMA_REGION (ASIC_BASE+0x884)
1.38 +
1.39 +void dmac_dump_channel( FILE *f, unsigned int channel )
1.40 +{
1.41 + fprintf( f, "DMAC SAR: %08X Count: %08X Ctl: %08X OR: %08X\n",
1.42 + long_read(DMA_SAR(channel)), long_read(DMA_TCR(channel)),
1.43 + long_read(DMA_CHCR(channel)), long_read(DMA_OR) );
1.44 +}
1.45 +
1.46 +
1.47 +/**
1.48 + * Setup the DMAC for a transfer. Assumes 32-byte block transfer.
1.49 + * Caller is responsible for making sure no-one else is using the
1.50 + * channel already.
1.51 + *
1.52 + * @param channel DMA channel to use, 0 to 3
1.53 + * @param source source address (if a memory source)
1.54 + * @param dest destination address (if a memory destination)
1.55 + * @param length number of bytes to transfer (must be a multiple of
1.56 + * 32.
1.57 + * @param direction 0 = host to device, 1 = device to host
1.58 + */
1.59 +void dmac_prepare_channel( int channel, uint32_t source, uint32_t dest,
1.60 + uint32_t length, int direction )
1.61 +{
1.62 + uint32_t control;
1.63 +
1.64 + if( direction == 0 ) {
1.65 + /* DMA Disabled, IRQ disabled, 32 byte transfer, burst mode,
1.66 + * Memory => Device, Source addr increment, dest addr fixed
1.67 + */
1.68 + control = 0x000012C0;
1.69 + } else {
1.70 + /* DMA Disabled, IRQ disabled, 32 byte transfer, burst mode,
1.71 + * Device => Memory, Source addr fixed, dest addr increment
1.72 + */
1.73 + control = 0x000043C0;
1.74 + }
1.75 + long_write( DMA_CHCR(channel), control );
1.76 + long_write( DMA_SAR(channel), source );
1.77 + long_write( DMA_DAR(channel), dest );
1.78 + long_write( DMA_TCR(channel), (length >> 5) );
1.79 + control |= 0x0001;
1.80 + long_write( DMA_CHCR(channel), control ); /* Enable DMA channel */
1.81 + long_write( DMA_OR, 0x8201 ); /* Ensure the DMAC config is set */
1.82 +}
1.83 +
1.84 +
1.85 +int pvr_dma_write( unsigned int target, char *buf, int len, int region )
1.86 +{
1.87 + uint32_t addr =(uint32_t)buf;
1.88 + int result;
1.89 + if( (addr & 0xFFFFFFE0) != addr ) {
1.90 + fprintf( stderr, "Address error: Attempting DMA from %08X\n", addr );
1.91 + return -1;
1.92 + } else {
1.93 + fprintf( stderr, "PVR DMA transfer from %08X\n", addr );
1.94 + }
1.95 + long_write( PVR_DMA_CTL, 0 ); /* Stop PVR dma if it's already running */
1.96 + asic_clear();
1.97 +
1.98 + dmac_prepare_channel( 2, (uint32_t)buf, 0, len, 0 ); /* Allocate channel 2 */
1.99 + long_write( PVR_DMA_DEST, target );
1.100 + long_write( PVR_DMA_COUNT, len );
1.101 + long_write( PVR_DMA_REGION, region );
1.102 +
1.103 + CHECK_IEQUALS( target, long_read(PVR_DMA_DEST) );
1.104 + CHECK_IEQUALS( len, long_read(PVR_DMA_COUNT) );
1.105 + CHECK_IEQUALS( 0, long_read(PVR_DMA_REGION) );
1.106 + CHECK_IEQUALS( (uint32_t)buf, long_read(DMA_SAR(2)) );
1.107 + CHECK_IEQUALS( len/32, long_read(DMA_TCR(2)) );
1.108 + CHECK_IEQUALS( 0x12C1, long_read(DMA_CHCR(2)) );
1.109 +
1.110 + long_write( PVR_DMA_CTL, 1 );
1.111 + result = asic_wait(EVENT_PVR_DMA);
1.112 +
1.113 + if( result != 0 ) {
1.114 + fprintf( stderr, "PVR DMA failed (timeout)\n" );
1.115 + asic_dump(stderr);
1.116 + fprintf( stderr, "Dest: %08X Count: %08X Ctl: %08X\n", long_read(PVR_DMA_DEST),
1.117 + long_read(PVR_DMA_COUNT), long_read(PVR_DMA_CTL) );
1.118 + dmac_dump_channel(stderr, 2);
1.119 + long_write( PVR_DMA_CTL, 0 );
1.120 + }
1.121 +
1.122 + CHECK_IEQUALS( 0, long_read(PVR_DMA_CTL) );
1.123 + CHECK_IEQUALS( ((uint32_t)buf)+len, long_read(DMA_SAR(2)) );
1.124 + CHECK_IEQUALS( 0, long_read(DMA_TCR(2)) );
1.125 + CHECK_IEQUALS( 0x12C3, long_read(DMA_CHCR(2)) );
1.126 + CHECK_IEQUALS( target, long_read(PVR_DMA_DEST) );
1.127 + CHECK_IEQUALS( 0, long_read(PVR_DMA_COUNT) );
1.128 + CHECK_IEQUALS( 0, long_read(PVR_DMA_REGION) );
1.129 +
1.130 + return result;
1.131 +}
.