1 /*
2 Copyright (c) 2002-04, Thomas Kurschel
3
4
5 Part of Radeon accelerant
6
7 DMA engine handling.
8
9 Currently, VID DMA is always used and data is always copied from
10 graphics memory to other memory.
11 */
12
13 #include "radeon_driver.h"
14 #include "mmio.h"
15 #include "rbbm_regs.h"
16 #include "dma_regs.h"
17 #include <string.h>
18
19 // this is arbitrary and hopefully sufficiently high
20 #define RADEON_MAX_DMA_SIZE 16*1024*1024
21
22
23 // initialize DMA engine
Radeon_InitDMA(device_info * di)24 status_t Radeon_InitDMA( device_info *di )
25 {
26 status_t res;
27
28 // allocate descriptor table in graphics mem
29 // (docu says that is _must_ be in graphics mem)
30 di->dma_desc_max_num = RADEON_MAX_DMA_SIZE / 4096;
31
32 res = mem_alloc( di->memmgr[mt_local], di->dma_desc_max_num * sizeof( DMA_descriptor ), 0,
33 &di->dma_desc_handle, &di->dma_desc_offset );
34
35 if( res != B_OK )
36 return res;
37
38 // allow DMA IRQ
39 OUTREGP( di->regs, RADEON_GEN_INT_CNTL, RADEON_VIDDMA_MASK, ~RADEON_VIDDMA_MASK );
40 // acknowledge possibly pending IRQ
41 OUTREG( di->regs, RADEON_GEN_INT_STATUS, RADEON_VIDDMA_AK );
42
43 return B_OK;
44 }
45
46
47 // prepare DMA engine to copy data from graphics mem to other mem
Radeon_PrepareDMA(device_info * di,uint32 src,char * target,size_t size,bool lock_mem,bool contiguous)48 static status_t Radeon_PrepareDMA(
49 device_info *di, uint32 src, char *target, size_t size, bool lock_mem, bool contiguous )
50 {
51 physical_entry map[16];
52 status_t res;
53 DMA_descriptor *cur_desc;
54 int num_desc;
55
56 if( lock_mem && !contiguous ) {
57 res = lock_memory( target, size, B_DMA_IO | B_READ_DEVICE );
58
59 if( res != B_OK ) {
60 SHOW_ERROR( 2, "Cannot lock memory (%s)", strerror( res ));
61 return res;
62 }
63 }
64
65 // adjust virtual address for graphics card
66 src += di->si->memory[mt_local].virtual_addr_start;
67
68 cur_desc = (DMA_descriptor *)(di->si->local_mem + di->dma_desc_offset);
69 num_desc = 0;
70
71 // memory may be fragmented, so we create S/G list
72 while( size > 0 ) {
73 int i;
74
75 if( contiguous ) {
76 // if memory is contiguous, ask for start address only to reduce work
77 get_memory_map( target, 1, map, 16 );
78 // replace received size with total size
79 map[0].size = size;
80 } else {
81 get_memory_map( target, size, map, 16 );
82 }
83
84 for( i = 0; i < 16; ++i ) {
85 phys_addr_t address = map[i].address;
86 size_t contig_size = map[i].size;
87
88 if( contig_size == 0 )
89 break;
90
91 #if B_HAIKU_PHYSICAL_BITS > 32
92 if (address + contig_size > (phys_addr_t)1 << 32) {
93 SHOW_ERROR(2, "Physical address > 4 GB: %#" B_PRIxPHYSADDR
94 "size: %#" B_PRIxSIZE, address, size);
95 res = B_BAD_VALUE;
96 goto err;
97 }
98 #endif
99
100 target += contig_size;
101
102 while( contig_size > 0 ) {
103 size_t cur_size;
104
105 cur_size = min( contig_size, RADEON_DMA_DESC_MAX_SIZE );
106
107 if( ++num_desc > (int)di->dma_desc_max_num ) {
108 SHOW_ERROR( 2, "Overflow of DMA descriptors, %ld bytes left", size );
109 res = B_BAD_VALUE;
110 goto err;
111 }
112
113 cur_desc->src_address = src;
114 cur_desc->dest_address = address;
115 cur_desc->command = cur_size;
116 cur_desc->res = 0;
117
118 ++cur_desc;
119 address += cur_size;
120 contig_size -= cur_size;
121 src += cur_size;
122 size -= cur_size;
123 }
124 }
125 }
126
127 // mark last descriptor as being last one
128 (cur_desc - 1)->command |= RADEON_DMA_COMMAND_EOL;
129
130 return B_OK;
131
132 err:
133 if( lock_mem && !contiguous )
134 unlock_memory( target, size, B_DMA_IO| B_READ_DEVICE );
135
136 return res;
137 }
138
139
140 // finish DMA
141 // caller must ensure that DMA channel has stopped
Radeon_FinishDMA(device_info * di,uint32 src,char * target,size_t size,bool lock_mem,bool contiguous)142 static void Radeon_FinishDMA(
143 device_info *di, uint32 src, char *target, size_t size, bool lock_mem, bool contiguous )
144 {
145 if( lock_mem && !contiguous )
146 unlock_memory( target, size, B_DMA_IO| B_READ_DEVICE );
147 }
148
149
150 // copy from graphics memory to other memory via DMA
151 // src - offset in graphics mem
152 // target - target address
153 // size - number of bytes to copy
154 // lock_mem - true, if memory is not locked
155 // contiguous - true, if memory is physically contiguous (implies lock_mem=false)
Radeon_DMACopy(device_info * di,uint32 src,char * target,size_t size,bool lock_mem,bool contiguous)156 status_t Radeon_DMACopy(
157 device_info *di, uint32 src, char *target, size_t size, bool lock_mem, bool contiguous )
158 {
159 status_t res;
160
161 /*SHOW_FLOW( 0, "src=%ld, target=%p, size=%ld, lock_mem=%d, contiguous=%d",
162 src, target, size, lock_mem, contiguous );*/
163
164 res = Radeon_PrepareDMA( di, src, target, size, lock_mem, contiguous );
165 if( res != B_OK )
166 return res;
167
168 //SHOW_FLOW0( 0, "2" );
169
170 OUTREG( di->regs, RADEON_DMA_VID_TABLE_ADDR, di->si->memory[mt_local].virtual_addr_start +
171 di->dma_desc_offset );
172
173 res = acquire_sem_etc( di->dma_sem, 1, B_RELATIVE_TIMEOUT, 1000000 );
174
175 // be sure that transmission is really finished
176 while( (INREG( di->regs, RADEON_DMA_VID_STATUS ) & RADEON_DMA_STATUS_ACTIVE) != 0 ) {
177 SHOW_FLOW0( 0, "DMA transmission still active" );
178 snooze( 1000 );
179 }
180
181 Radeon_FinishDMA( di, src, target, size, lock_mem, contiguous );
182
183 //SHOW_FLOW0( 0, "3" );
184
185 return res;
186 }
187