Blame view

app/app-prime-modbus/lib/common/tmmap.c 4.02 KB
8c2952457   김태훈   응용 프로그램 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
  /**    
      @file     tmmap.c
      @date     2009/07/06
      @author   오재경 freefrug@falinux.com  FALinux.Co.,Ltd.
      @brief    mmap 를 다루는 함수를 객체화 하였다.
                
      @todo     테스트 함수를 아직 만들지 않았다.
      @bug     
      @remark  
      @warning 
  */
  //
  //  저작권    에프에이리눅스(주)
  //            외부공개 금지
  //
  //----------------------------------------------------------------------------
  
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>
  #include <string.h>
  #include <fcntl.h>
  #include <sys/ioctl.h>
  #include <sys/time.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/poll.h>
  #include <sys/mman.h> 
  
  
  #include <tlist.h>
  #include <tmmap.h>
  
  
  /// mmap 를 위한 개별 관리 구조체
  typedef struct {
  	
  	int            dev;         // /dev/mem 파일핸들
  	unsigned long  phys;        // 물리주소
  	unsigned long  size;        // 크기
  	int            base_ofs;    // 베이스 주소가 4K 정렬이 되지 않았을때 사용
  
  	void          *virt;        // 할당받은 메모리포인터
  	
  } mmap_alloc_t;
  
  
  static tlist *ma_list = NULL;   /// mmap 관리 리스트
  
  
  //------------------------------------------------------------------------------
  /** @brief   mmap 생성함수
      @param   base
      @param   size
  *///----------------------------------------------------------------------------
  void  *tmmap_alloc( unsigned long phys_base, unsigned long size )
  {       
  	int            dev_mem;
  	int            base_ofs;
  	void          *mmap_mem;
  	mmap_alloc_t  *ma;
  	
  	// 관리 리스트를 생성한다.
  	if ( NULL == ma_list )
  	{
  		ma_list = tlist_create();	
  	}
  	
  	// 4K 정렬 주소로 변경한다.
  	base_ofs   = phys_base & (PAGE_SIZE-1);
  	phys_base &= ~(PAGE_SIZE-1);
  	
  	// 4K 단위의 메모리를 할당받는다.
  	size = PAGE_SIZE * ( (size + base_ofs + (PAGE_SIZE-1))/(PAGE_SIZE) );
  	
  	dev_mem = open( "/dev/mem", O_RDWR|O_SYNC );
  	if (0 > dev_mem)
  	{
  		printf( "open error /dev/mem
  " );
  		return NULL;
  	}
  
  	// mmap 로 맵핑한다.
  	mmap_mem = mmap( 0,                                // 커널에서 알아서 할당요청
                       size,                             // 할당 크기
                       PROT_READ|PROT_WRITE, MAP_SHARED, // 할당 속성
                       dev_mem,                          // 파일 핸들
                       phys_base );                      // 매핑 대상의 물리주소	
  	
  	
  	if ( !mmap_mem )
  	{
  		printf( "mmap error !!!
  " );
  		return NULL;
  	}
  
  	// 개별 관리를 위한 구조체를 할당한다.
  	ma = (mmap_alloc_t  *)malloc( sizeof(mmap_alloc_t) );
  	ma->dev      = dev_mem;
  	ma->phys     = phys_base;
  	ma->size     = size;
  	ma->virt     = mmap_mem;
  	ma->base_ofs = base_ofs;
  
  	// 관리 리스트에 등록한다.
  	tlist_add( ma_list, (void *)ma );
  
  	return mmap_mem + base_ofs;
  }
  //------------------------------------------------------------------------------
  /** @brief   mmap로 획드한 메모리 포인터를 이용하여 관리 구조체를 얻는다.
      @param   virt   mmap 로 획드한 메모리 포인터
      @return  인덱스
  *///----------------------------------------------------------------------------
  static int tmmap_get_index( void *virt )
  {
  	mmap_alloc_t  *ma;
  	int  idx, count;
  	
  	if ( ma_list )
  	{
  		count = tlist_getcount( ma_list );
  		for (idx=0; idx<count; idx++ )
  		{
  			ma = (mmap_alloc_t *)tlist_get( ma_list, idx );
  			
  			// 가상메모리가 동일한 주소인지 확인한다.
  			if( (ma->virt + ma->base_ofs) == virt )
  			{
  				return idx;
  			}
  		}
  	}
  	
  	return -1;
  }
  //------------------------------------------------------------------------------
  /** @brief   mmap  포인터를 해제한다.
      @param   mem   mmap 로 획드한 메모리 포인터
  *///----------------------------------------------------------------------------
  void  tmmap_free( void *mem )
  {
  	int  idx;
  	mmap_alloc_t  *ma;
  		
  	if ( ma_list && mem )
  	{
  		// 해당하는 아이템을 찾아 메모리를 해제한다.
  		idx = tmmap_get_index( mem );
  		if ( 0 <= idx )
  		{
  			ma = (mmap_alloc_t *)tlist_get( ma_list, idx );
  			
  			munmap( ma->virt, ma->size );	
  			close ( ma->dev );
  			
  			free( (void *)ma );
  			tlist_delete( ma_list, idx );
  		} 
  
  		// 아이템이 없다면 관리자도 해제한다.
  		if ( 0 >= tlist_getcount( ma_list ) )
  		{
  			tlist_free( ma_list );
  			ma_list = NULL;
  		}
  
  	}
  }