tmmap.c
4.02 KB
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
/**
@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\n" );
return NULL;
}
// mmap 로 맵핑한다.
mmap_mem = mmap( 0, // 커널에서 알아서 할당요청
size, // 할당 크기
PROT_READ|PROT_WRITE, MAP_SHARED, // 할당 속성
dev_mem, // 파일 핸들
phys_base ); // 매핑 대상의 물리주소
if ( !mmap_mem )
{
printf( "mmap error !!!\n" );
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;
}
}
}