본문 바로가기
실습/리눅스 커널

DMA 처리

by 써드아이 2021. 2. 8.

[블로그 통합으로 이전해 온 자료] - 2008. 4. 29. 20:58

 

 

* DMA

 DMA 할당/해제
 
 int request_dma( unsigned int dma, const char *device_id );
 void free_dma( unsigned int dma );


 DMA를 위한 메모리 할당/해제
 
 void *dma_alloc_coherent( struct device *dev, size_t size, dma_addr_t *dma_handle, int flags );
 void *dma_free_coherent( struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle );


 unsigned long clain_dma_lock( void );
 void disable_dma( unsigned int dma );
 void clear_dma_ff( unsigned int dma );
 void set_dma_mode( unsigned int dma, char mode );
 void set_dma_addr( unsigned int dma, unsigned int a );
 void set_dma_count( unsigned int dma, unsigned int count );
 void enable_dma( unsigned int dma );
 void release_dma_lock( unsigned long flags );
 int get_dma_residue( unsigned int dma );


- DMA 전송 준비 함수 / DMA 완료 점검 함수 필요

 unsigned template_dma_prepare( int channel, int mode, unsigned int buf, unsigned int count )
 {
  unsigned long flags = claim_dma_lock();
 
  disable_dma( channel );
  clear_dma_ff( channel );
  set_dma_mode( channel, mode );
  set_dma_addr( channel, virt_to_bus( buf ) );
  set_dma_count( channel, count );
  enable_dma( channel );
  release_dma_lock( flags );
 
  return 0;
 }
 
 int template_dma_isdone( int channel )
 {
  int residue;
  unsigned long flags = claim_dma_lock( );
 
  residue = get_dma_residue( channel );
  release_dma_lock( flags );
 
  return ( residue == 0 );
 }
 
 SetPageReserved( ) 할당된 페이지를 예약
 ClearPageReserved( ) 예약된 페이지의 해제
 

 file_operations 구조체의 mmap 필드
 
 int dma_mmap_mmap( struct file *filp, struct vm_area_struct *vma )
 {
  unsigned long phys_addr;
 
  phys_addr = virt_to_phys( dmabuff )
 
  if ( remap_page_range( vma, vma->vm_start, phys_addr, DMA_BUFF_SIZE, vma->vm_page_prot ) )
   return -EAGAIN;
 
  return 0;
 }

'실습 > 리눅스 커널' 카테고리의 다른 글

디바이스 드라이버의 동작  (0) 2021.02.08
Major, Minor #  (0) 2021.02.08
Memory Mapping  (0) 2021.02.08
인터럽트 (Interrupt) 처리  (0) 2021.02.08
커널 타이머, 태스크릿, 작업큐  (0) 2021.02.08