filename | test/dmac.c |
changeset | 815:866c103d72cd |
prev | 812:8cc61d5ea1f8 |
author | nkeynes |
date | Mon Jan 17 21:22:06 2011 +1000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Avoid rebinding textures unnecessarily (actually saves a surprising amount of runtime) |
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 }
.