/** @file tmmap.c @date 2009/07/06 @author 오재경 freefrug@falinux.com FALinux.Co.,Ltd. @brief mmap 를 다루는 함수를 객체화 하였다. @todo 테스트 함수를 아직 만들지 않았다. @bug @remark @warning */ // // 저작권 에프에이리눅스(주) // 외부공개 금지 // //---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include /// 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; idxvirt + 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; } } }