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 Tue Jan 01 05:08:38 2008 +0000 (12 years ago)
branchlxdream-mmu
permissions -rw-r--r--
last change Enable Id keyword on all source files
file annotate diff log raw
nkeynes@185
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@185
     3
 * 
nkeynes@185
     4
 * DMA support code
nkeynes@185
     5
 *
nkeynes@185
     6
 * Copyright (c) 2006 Nathan Keynes.
nkeynes@185
     7
 *
nkeynes@185
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@185
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@185
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@185
    11
 * (at your option) any later version.
nkeynes@185
    12
 *
nkeynes@185
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@185
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@185
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@185
    16
 * GNU General Public License for more details.
nkeynes@185
    17
 */
nkeynes@185
    18
nkeynes@185
    19
#include "dma.h"
nkeynes@185
    20
#include "asic.h"
nkeynes@185
    21
nkeynes@185
    22
#define DMA_BASE 0xFFA00000
nkeynes@185
    23
nkeynes@185
    24
#define DMA_SAR(c) (DMA_BASE+0x00+(c<<4))
nkeynes@185
    25
#define DMA_DAR(c) (DMA_BASE+0x04+(c<<4))
nkeynes@185
    26
#define DMA_TCR(c) (DMA_BASE+0x08+(c<<4))
nkeynes@185
    27
#define DMA_CHCR(c) (DMA_BASE+0x0C+(c<<4))
nkeynes@185
    28
#define DMA_OR (DMA_BASE+0x40)
nkeynes@185
    29
nkeynes@185
    30
#define ASIC_BASE 0xA05F6000
nkeynes@185
    31
#define PVR_DMA_DEST  (ASIC_BASE+0x800)
nkeynes@185
    32
#define PVR_DMA_COUNT (ASIC_BASE+0x804)
nkeynes@185
    33
#define PVR_DMA_CTL   (ASIC_BASE+0x808)
nkeynes@185
    34
#define PVR_DMA_REGION (ASIC_BASE+0x884)
nkeynes@185
    35
nkeynes@185
    36
void dmac_dump_channel( FILE *f, unsigned int channel )
nkeynes@185
    37
{
nkeynes@185
    38
    fprintf( f, "DMAC SAR: %08X  Count: %08X  Ctl: %08X  OR: %08X\n",
nkeynes@185
    39
	     long_read(DMA_SAR(channel)), long_read(DMA_TCR(channel)), 
nkeynes@185
    40
	     long_read(DMA_CHCR(channel)), long_read(DMA_OR) );
nkeynes@185
    41
}
nkeynes@185
    42
nkeynes@185
    43
nkeynes@185
    44
/**
nkeynes@185
    45
 * Setup the DMAC for a transfer. Assumes 32-byte block transfer.
nkeynes@185
    46
 * Caller is responsible for making sure no-one else is using the
nkeynes@185
    47
 * channel already. 
nkeynes@185
    48
 *
nkeynes@185
    49
 * @param channel DMA channel to use, 0 to 3
nkeynes@185
    50
 * @param source source address (if a memory source)
nkeynes@185
    51
 * @param dest   destination address (if a memory destination)
nkeynes@185
    52
 * @param length number of bytes to transfer (must be a multiple of
nkeynes@185
    53
 *               32.
nkeynes@185
    54
 * @param direction 0 = host to device, 1 = device to host
nkeynes@185
    55
 */
nkeynes@185
    56
void dmac_prepare_channel( int channel, uint32_t source, uint32_t dest,
nkeynes@185
    57
			   uint32_t length, int direction )
nkeynes@185
    58
{
nkeynes@185
    59
    uint32_t control;
nkeynes@185
    60
nkeynes@185
    61
    if( direction == 0 ) {
nkeynes@185
    62
	/* DMA Disabled, IRQ disabled, 32 byte transfer, burst mode,
nkeynes@185
    63
	 * Memory => Device, Source addr increment, dest addr fixed
nkeynes@185
    64
	 */
nkeynes@185
    65
	control = 0x000012C0;
nkeynes@185
    66
    } else {
nkeynes@185
    67
	/* DMA Disabled, IRQ disabled, 32 byte transfer, burst mode,
nkeynes@185
    68
	 * Device => Memory, Source addr fixed, dest addr increment
nkeynes@185
    69
	 */
nkeynes@185
    70
	control = 0x000043C0;
nkeynes@185
    71
    }
nkeynes@185
    72
    long_write( DMA_CHCR(channel), control );
nkeynes@185
    73
    long_write( DMA_SAR(channel), source );
nkeynes@185
    74
    long_write( DMA_DAR(channel), dest );
nkeynes@185
    75
    long_write( DMA_TCR(channel), (length >> 5) );
nkeynes@185
    76
    control |= 0x0001;
nkeynes@185
    77
    long_write( DMA_CHCR(channel), control ); /* Enable DMA channel */
nkeynes@185
    78
    long_write( DMA_OR, 0x8201 ); /* Ensure the DMAC config is set */
nkeynes@185
    79
}
nkeynes@185
    80
nkeynes@185
    81
nkeynes@185
    82
int pvr_dma_write( unsigned int target, char *buf, int len, int region )
nkeynes@185
    83
{
nkeynes@185
    84
    uint32_t addr =(uint32_t)buf;
nkeynes@185
    85
    int result;
nkeynes@185
    86
    if( (addr & 0xFFFFFFE0) != addr ) {
nkeynes@185
    87
	fprintf( stderr, "Address error: Attempting DMA from %08X\n", addr );
nkeynes@185
    88
	return -1;
nkeynes@185
    89
    }
nkeynes@185
    90
    long_write( PVR_DMA_CTL, 0 ); /* Stop PVR dma if it's already running */
nkeynes@185
    91
    asic_clear();
nkeynes@185
    92
nkeynes@185
    93
    dmac_prepare_channel( 2, (uint32_t)buf, 0, len, 0 ); /* Allocate channel 2 */
nkeynes@185
    94
    long_write( PVR_DMA_DEST, target );
nkeynes@185
    95
    long_write( PVR_DMA_COUNT, len );
nkeynes@185
    96
    long_write( PVR_DMA_REGION, region );
nkeynes@185
    97
nkeynes@185
    98
    CHECK_IEQUALS( target, long_read(PVR_DMA_DEST) );
nkeynes@185
    99
    CHECK_IEQUALS( len, long_read(PVR_DMA_COUNT) );
nkeynes@185
   100
    CHECK_IEQUALS( 0, long_read(PVR_DMA_REGION) );
nkeynes@185
   101
    CHECK_IEQUALS( (uint32_t)buf, long_read(DMA_SAR(2)) );
nkeynes@185
   102
    CHECK_IEQUALS( len/32, long_read(DMA_TCR(2)) );
nkeynes@185
   103
    CHECK_IEQUALS( 0x12C1, long_read(DMA_CHCR(2)) );
nkeynes@185
   104
nkeynes@185
   105
    long_write( PVR_DMA_CTL, 1 );
nkeynes@185
   106
    result = asic_wait(EVENT_PVR_DMA);
nkeynes@185
   107
nkeynes@185
   108
    if( result != 0 ) {
nkeynes@185
   109
	fprintf( stderr, "PVR DMA failed (timeout)\n" );
nkeynes@185
   110
	asic_dump(stderr);
nkeynes@185
   111
	fprintf( stderr, "Dest: %08X  Count: %08X  Ctl: %08X\n", long_read(PVR_DMA_DEST),
nkeynes@185
   112
		 long_read(PVR_DMA_COUNT), long_read(PVR_DMA_CTL) );
nkeynes@185
   113
	dmac_dump_channel(stderr, 2);
nkeynes@185
   114
	long_write( PVR_DMA_CTL, 0 );
nkeynes@185
   115
    }
nkeynes@185
   116
nkeynes@185
   117
    CHECK_IEQUALS( 0, long_read(PVR_DMA_CTL) );
nkeynes@185
   118
    CHECK_IEQUALS( ((uint32_t)buf)+len, long_read(DMA_SAR(2))  );
nkeynes@185
   119
    CHECK_IEQUALS( 0, long_read(DMA_TCR(2)) );
nkeynes@185
   120
    CHECK_IEQUALS( 0x12C3, long_read(DMA_CHCR(2)) );
nkeynes@185
   121
    CHECK_IEQUALS( target, long_read(PVR_DMA_DEST) );
nkeynes@185
   122
    CHECK_IEQUALS( 0, long_read(PVR_DMA_COUNT) );
nkeynes@185
   123
    CHECK_IEQUALS( 0, long_read(PVR_DMA_REGION) );
nkeynes@185
   124
nkeynes@185
   125
    return result;
nkeynes@185
   126
}
.