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 Sat Jun 14 11:54:15 2008 +0000 (15 years ago)
permissions -rw-r--r--
last change Change colour params to float
Convert background processing over to scene structure (fixes some depth issues as well)
Add color unclamp when supported
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
}
.