Changeset 343 for soft/giet_vm/giet_drivers/dma_driver.c
- Timestamp:
- Jun 24, 2014, 4:41:44 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_drivers/dma_driver.c
r333 r343 152 152 // and sets the transfer size to lauch the transfer. 153 153 ////////////////////////////////////////////////////////////////////////////////// 154 unsigned int _dma_start_transfer( unsigned int cluster_xy, 155 unsigned int channel_id, 156 unsigned long long dst_paddr, // physical address 157 unsigned long long src_paddr, // physical address 158 unsigned int size ) // bytes 159 { 160 #if NB_DMA_CHANNELS > 0 161 162 // parameters checking 163 unsigned int x = cluster_xy >> Y_WIDTH; 164 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 165 if (x >= X_SIZE) return 1; 166 if (y >= Y_SIZE) return 1; 167 if (channel_id >= NB_DMA_CHANNELS) return 1; 154 void _dma_start_transfer( unsigned int cluster_xy, // DMA cluster 155 unsigned int channel_id, // DMA channel 156 unsigned long long dst_paddr, // physical address 157 unsigned long long src_paddr, // physical address 158 unsigned int size ) // bytes 159 { 160 #if NB_DMA_CHANNELS > 0 168 161 169 162 // compute DMA base address … … 177 170 dma_address[channel_id * DMA_SPAN + DMA_DST_EXT] = (unsigned int)(dst_paddr>>32); 178 171 dma_address[channel_id * DMA_SPAN + DMA_LEN] = (unsigned int)size; 179 return 0; 180 #else 181 return 1; 182 #endif 183 } 184 /////////////////////////////////////////////////////////////////////////////////// 185 // This function copies a source memory buffer to a destination memory buffer, 186 // using the distributed DMA. As it makes virtual to physical address translation, 187 // the MMU should be activated. 188 // This driver makes the assumption that each processor has a private DMA channel: 189 // the DMA cluster and channel indexes are obtained from the processor index. 172 173 #endif 174 } 175 176 /////////////////////////////////////////////////////////////////////////////////// 177 // This function copies a source memory buffer to a destination memory buffer, 178 // using directly physical addresses. 179 // This blocking function is supposed to be used by the kernel only, 180 // and uses a polling policy on DMA_STATUS register to detect completion. 181 // Therefore, the DMA_IRQ is NOT used. 190 182 // The source and destination buffers base addresses must be word aligned, 191 183 // and the buffer's size must be multiple of 4. … … 193 185 // message is displayed on TTY0, and the system crash. 194 186 /////////////////////////////////////////////////////////////////////////////////// 195 // Note: this blocking function is supposed to be used by the kernel only, 196 // and uses a polling policy on DMA_STATUS register to detect completion. 197 // Therefore, the DMA_IRQ is NOT used. 198 /////////////////////////////////////////////////////////////////////////////////// 199 inline void _dma_copy( unsigned int vspace_id, // vspace index for V2P 200 void* dest, // dest buffer vbase 201 const void* source, // source buffer vbase 202 unsigned int size ) // bytes 203 { 204 #if NB_DMA_CHANNELS > 0 205 206 unsigned int procid = _get_procid(); 207 unsigned int cluster_xy = procid/NB_PROCS_MAX; 208 unsigned int channel_id = procid%NB_PROCS_MAX; 209 210 unsigned int ko; 211 unsigned int ppn; 212 unsigned int flags; 213 214 #if GIET_DEBUG_DMA_DRIVER 215 unsigned int x = cluster_xy >> Y_WIDTH; 216 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 217 218 _printf("\n[DMA DEBUG] Processor[%d,%d,%d] enters _dma_copy() at cycle %d\n" 219 " - vspace_id = %d\n" 220 " - src_vaddr = %x\n" 221 " - dst_vaddr = %x\n" 187 void _dma_physical_copy( unsigned int cluster_xy, // DMA cluster 188 unsigned int channel_id, // DMA channel 189 unsigned long long dst_paddr, // destination physical address 190 unsigned long long src_paddr, // source physical address 191 unsigned int size ) // bytes 192 { 193 #if NB_DMA_CHANNELS > 0 194 195 // check DMA channel parameters 196 unsigned int x = cluster_xy >> Y_WIDTH; 197 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 198 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) ) 199 { 200 _printf("\n[GIET ERROR] in _dma_physical_copy() : illegal DMA channel "); 201 _exit(); 202 } 203 204 // check buffers alignment constraints 205 if ( (dst_paddr & 0x3) || (src_paddr & 0x3) || (size & 0x3) ) 206 { 207 _printf("\n[GIET ERROR] in _dma_physical_copy() : buffer unaligned\n"); 208 _exit(); 209 } 210 211 #if GIET_DEBUG_DMA_DRIVER 212 _printf("\n[DMA DEBUG] Start a dma_physical_copy on channel[%d,%d,%d] at cycle %d\n" 213 " - src_paddr = %l\n" 214 " - dst_paddr = %l\n" 222 215 " - bytes = %x\n", 223 x, y, channel_id, _get_proctime(), vspace_id, 224 (unsigned int)source, (unsigned int)dest, size ); 225 #endif 226 227 // checking alignment constraints 228 if ( (((unsigned int)dest) & 0x3) || 229 (((unsigned int)source) & 0x3) || 230 (size & 0x3) ) 231 { 232 _printf("\n[GIET ERROR] in _dma_copy() : buffer unaligned\n"); 233 _exit(); 234 } 235 236 // get vspace 0 page table pointer 237 unsigned int pt = _ptabs_vaddr[vspace_id]; 238 239 // get source buffer physical addresse 240 ko = _v2p_translate( (page_table_t*)pt, // page table pointer 241 ((unsigned int)source)>>12, // vpn 242 &ppn, // ppn 243 &flags ); // flags 244 if ( ko ) 245 { 246 _printf("\n[GIET ERROR] in _dma_copy() : source buffer unmapped\n"); 247 _exit(); 248 } 249 unsigned long long src_paddr = (((unsigned long long)ppn) << 12) | 250 ((unsigned int)source & 0x00000FFF); 251 252 // get dest buffer physical addresse 253 ko = _v2p_translate( (page_table_t*)pt, // page table pointer 254 ((unsigned int)dest)>>12, // vpn 255 &ppn, // ppn 256 &flags ); // flags 257 if ( ko ) 258 { 259 _printf("\n[GIET ERROR] in _dma_copy() : dest buffer unmapped\n"); 260 _exit(); 261 } 262 unsigned long long dst_paddr = (((unsigned long long)ppn) << 12) | 263 ((unsigned int)dest & 0x00000FFF); 264 265 #if GIET_DEBUG_DMA_DRIVER 266 _printf(" - src_paddr = %l\n" 267 " - dst_paddr = %l\n", 268 src_paddr, dst_paddr ); 269 #endif 270 271 // invalidate L1 cache if no hardware cache coherence 272 if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( dest, size ); 216 x, y, channel_id, _get_proctime(), src_paddr, dst_paddr, size ); 217 #endif 273 218 274 219 // dma channel configuration & lauching 275 ko = _dma_start_transfer( cluster_xy, channel_id, dst_paddr, src_paddr, size ); 276 if ( ko ) 277 { 278 _printf("\n[GIET ERROR] in _dma_copy() : cannot start transfer\n"); 279 _exit(); 280 } 220 _dma_start_transfer( cluster_xy, channel_id, dst_paddr, src_paddr, size ); 281 221 282 222 // scan dma channel status … … 289 229 290 230 #if GIET_DEBUG_DMA_DRIVER 291 _printf("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register ...\n"); 231 _printf("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS register\n"); 232 #endif 233 234 } 235 236 // analyse status 237 if( status != DMA_SUCCESS ) 238 { 239 _printf("\n[GIET ERROR] in _dma_physical_copy() : DMA_STATUS = %x\n", status ); 240 _exit(); 241 } 242 // reset dma channel 243 _dma_reset( cluster_xy, channel_id ); 244 245 #if GIET_DEBUG_DMA_DRIVER 246 _printf("\n[DMA DEBUG] _dma_physical_copy() completed at cycle %d\n", _get_proctime() ); 247 #endif 248 249 #else // NB_DMA_CHANNELS == 0 250 _printf("\n[GIET ERROR] in _dma_physical_copy() : NB_DMA_CHANNELS == 0 / cycle %d\n", 251 _get_proctime ); 252 _exit(); 253 #endif 254 } 255 256 /////////////////////////////////////////////////////////////////////////////////// 257 // This function copies a source memory buffer to a destination memory buffer, 258 // making virtual to physical address translation: the MMU should be activated. 259 // This blocking function is supposed to be used by the kernel only, 260 // and uses a polling policy on DMA_STATUS register to detect completion. 261 // Therefore, the DMA_IRQ is NOT used. 262 // The source and destination buffers base addresses must be word aligned, 263 // and the buffer's size must be multiple of 4. 264 // In case of error (buffer unmapped, unaligned, or DMA_STATUS error), an error 265 // message is displayed on TTY0, and the system crash. 266 /////////////////////////////////////////////////////////////////////////////////// 267 void _dma_copy( unsigned int cluster_xy, // DMA cluster 268 unsigned int channel_id, // DMA channel 269 unsigned int vspace_id, // vspace index for v2p translation 270 unsigned int dst_vaddr, // dst_vaddr buffer vbase 271 unsigned int src_vaddr, // src_vaddr buffer vbase 272 unsigned int size ) // bytes 273 { 274 #if NB_DMA_CHANNELS > 0 275 276 // check DMA channel parameters 277 unsigned int x = cluster_xy >> Y_WIDTH; 278 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 279 if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) ) 280 { 281 _printf("\n[GIET ERROR] in _dma_copy() : illegal DMA channel "); 282 _exit(); 283 } 284 285 // check buffers alignment constraints 286 if ( (dst_vaddr & 0x3) || (src_vaddr & 0x3) || (size & 0x3) ) 287 { 288 _printf("\n[GIET ERROR] in _dma_copy() : buffer unaligned\n"); 289 _exit(); 290 } 291 292 unsigned int ko; 293 unsigned int ppn; 294 unsigned int flags; 295 296 #if GIET_DEBUG_DMA_DRIVER 297 _printf("\n[DMA DEBUG] Start a dma_copy on channel[%d,%d,%d] at cycle %d\n" 298 " - src_vaddr = %x\n" 299 " - dst_vaddr = %x\n" 300 " - bytes = %x\n", 301 x, y, channel_id, _get_proctime(), src_vaddr, dst_vaddr, size ); 302 #endif 303 304 // checking alignment constraints 305 if ( (((unsigned int)dst_vaddr) & 0x3) || 306 (((unsigned int)src_vaddr) & 0x3) || 307 (size & 0x3) ) 308 { 309 _printf("\n[GIET ERROR] in _dma_copy() : buffer unaligned\n"); 310 _exit(); 311 } 312 313 // get vspace page table pointer 314 unsigned int pt = _ptabs_vaddr[vspace_id]; 315 316 // get src_paddr buffer physical addresse 317 ko = _v2p_translate( (page_table_t*)pt, // page table pointer 318 src_vaddr>>12, // vpn 319 &ppn, // ppn 320 &flags ); // flags 321 if ( ko ) 322 { 323 _printf("\n[GIET ERROR] in _dma_copy() : source buffer unmapped\n"); 324 _exit(); 325 } 326 unsigned long long src_paddr = (((unsigned long long)ppn) << 12) | 327 (unsigned long long)(src_vaddr & 0x00000FFF); 328 329 // get dst_paddr buffer physical addresse 330 ko = _v2p_translate( (page_table_t*)pt, // page table pointer 331 dst_vaddr>>12, // vpn 332 &ppn, // ppn 333 &flags ); // flags 334 if ( ko ) 335 { 336 _printf("\n[GIET ERROR] in _dma_copy() : dest buffer unmapped\n"); 337 _exit(); 338 } 339 unsigned long long dst_paddr = (((unsigned long long)ppn) << 12) | 340 (unsigned long long)(dst_vaddr & 0x00000FFF); 341 342 #if GIET_DEBUG_DMA_DRIVER 343 _printf(" - src_paddr = %l\n" 344 " - dst_paddr = %l\n", 345 src_paddr, dst_paddr ); 346 #endif 347 348 // dma channel configuration & lauching 349 _dma_start_transfer( cluster_xy, channel_id, dst_paddr, src_paddr, size ); 350 351 // scan dma channel status 352 unsigned int status = _dma_get_status( cluster_xy, channel_id ); 353 while( (status != DMA_SUCCESS) && 354 (status != DMA_READ_ERROR) && 355 (status != DMA_WRITE_ERROR) ) 356 { 357 status = _dma_get_status( cluster_xy, channel_id ); 358 359 #if GIET_DEBUG_DMA_DRIVER 360 _printf("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register\n"); 292 361 #endif 293 362
Note: See TracChangeset
for help on using the changeset viewer.