Linux - 2.6.25 커 널 프레임 버퍼 장치 구동 분석

프레임 버퍼 (framebuffer) 장 치 는 Liux 디 스 플레이 기술 에 응용 된다.Liux 의 디 스 플레이 플랫폼 은 모두 framebuffer 를 바탕 으로 하기 때문에 현재 Liux 환경 에서 도형 화 인터페이스, 게임, 영상 소프트웨어 등 시각 화 응용 을 개발 할 때 반드시 프레임 버퍼 기술 을 사용 해 야 한다. 현재 소비 가 점점 오락 화 되 는 추세 에 따라 시각 화 응용 은 제품 개발 에서 점점 중요 해 지고 있다. 따라서프레임 버퍼 기술 에 대한 이해 와 파악 이 매우 중요 하 다.
1 Frambuffer 소개
     프레임 버퍼 는 Liux 시스템 에서 상부 응용 과 바 텀 디 스 플레이 장치 사이 에 있 습 니 다. 다음 그림 과 같 습 니 다.그의 디자인 의 도 는 상부 응용 에 대해 저층 의 서로 다른 하드웨어 의 조작 디 테 일 을 차단 하 는 것 이다. 서로 다른 공장 의 서로 다른 유형의 디 스 플레이 하드웨어 에 대해 각 업 체 가 기술적 으로 장점 을 살 리 고 단점 을 피 하 는 수요 가 있 기 때문에 구체 적 인 디 테 일, 예 를 들 어 레지스터 의 수량 과 종류의 디자인 에 있어 상당 한 차이 가 존재 할 것 이다.또한 각 레지스터 의 초기 화 에 대한 정의 와 리드 신호 에 대한 정의 도 비슷 하지 않다. 이 는 두 가지 성능 이 비슷 한 제품 이라도 예 를 들 어 샤프 3.5 인치 LCD 모듈 과 삼 성의 3.5 인치 모듈 은 조작 디 테 일이 다르다.그래 픽 인터페이스 개발 에 능 한 개발 자 들 로 하여 금 하드웨어 범주 에 속 하 는 액정 모듈 레지스터 의 기록 순서 문 제 를 궁리 하 게 한다 면 큰 낭비 일 것 이다.따라서 개발 자의 시간 과 정력 을 절약 하기 위해 상부 개발 과 하부 설비 사이 에 중간 층 을 넣 어야 한다.
 
2 Frambuffer 디 스 플레이 원리
     프레임 버퍼 는 사용자 프로 세 스 의 데 이 터 를 저장 한 다음 디 스 플레이 장치 에 입력 하 는 저수지 와 유사 합 니 다.사용자 에 게 프레임 버퍼 는 메모리 의 한 구역 으로 읽 기, 쓰기, 매 핑 이 가능 합 니 다.초기 화 단계 에서 디 스 플레이 장 치 를 사용자 프로 세 스 공간 에 표시 하면 화면의 모든 점 과 프레임 버퍼 의 모든 점 을 일일이 대응 하 는 것 으로 이해 할 수 있 습 니 다.이렇게 하면 이 메모리 영역 에 정 의 된 픽 셀 과 색상 을 채 울 수 있 고 화면 도 방금 기 록 된 픽 셀 과 색상 에 따라 다채로운 화면 을 나 타 낼 수 있 습 니 다.
3 2.6.25 커 널 Frambuffer 와 관련 된 데이터 구조
     관련 데이터 구 조 는 운영 환경 에서 사용자 공간 과 커 널 공간 두 가지 로 나 눌 수 있다.사용자 공간 에서 사용 하 는 데이터 구 조 는 주로 fbfix_screenfo 와 fbvar_screeninfo。커 널 공간 에서 사용 하 는 주요 데이터 구 조 는 fb 입 니 다.info。
     먼저 fb 소개fix_screenfo, 이 데이터 구 조 는 시스템 이 실행 되 는 동안 변경 할 수 없 는 정 보 를 정의 합 니 다. 예 를 들 어 장치 이름, 화면의 픽 셀 수량, 버퍼 의 첫 주소 와 길이 등 입 니 다.이런 정 보 는 일반적으로 ioctl 함 수 를 통 해 얻 을 수 있다.다음은 fbfix_screenfo 의 주요 내용:
C/C++ code

    
    
    
    
struct fb_fix_screeninfo {

    
    
    
    
char id[ 16 ]; /* */

    
    
    
    
unsigned long smem_start; /* frame buffer ( ) */

    
    
    
    
__u32 smem_len; /* */

    
    
    
    
__u32 type; /* , TFT STN */ ……

    
    
    
    
__u32 visual; /* , 、 */

    
    
    
    
……

    
    
    
    
__u32 line_length; /* */

    
    
    
    
unsigned long mmio_start; /* IO ( ) */

    
    
    
    
__u32 mmio_len; /* IO */

    
    
    
    
__u32 accel; /* */

    
    
    
    
__u16 reserved[ 3 ]; /* */ };
 
  
     相对应的,fb_var_screeninfo定义了一些在系统运行期间可以改变的信息。例如像素深度、灰度级、颜色格式、时序,屏幕边缘空白区等。下表中列出了fb_var_screeninfo的主要内容:
C/C++ code

    
    
    
    
struct fb_var_screeninfo {

    
    
    
    
__u32 xres; /* visible resolution */

    
    
    
    
__u32 yres;

    
    
    
    
__u32 xres_virtual; /* virtual resolution */

    
    
    
    
__u32 yres_virtual;

    
    
    
    
__u32 xoffset; /* */

    
    
    
    
__u32 yoffset;

    
    
    
    
 

    
    
    
    
__u32 bits_per_pixel; /* */

    
    
    
    
__u32 grayscale; /* */

    
    
    
    

    
    
    
    
struct fb_bitfield red;

    
    
    
    
struct fb_bitfield green;

    
    
    
    
struct fb_bitfield blue;

    
    
    
    
struct fb_bitfield transp; /* */

    
    
    
    
 

    
    
    
    
__u32 nonstd; /* */

    
    
    
    
……

    
    
    
    
__u32 pixclock; /* */

    
    
    
    
__u32 left_margin; /* */

    
    
    
    
__u32 right_margin; /* */

    
    
    
    
__u32 upper_margin; /* */

    
    
    
    
__u32 lower_margin;

    
    
    
    
__u32 hsync_len; /* */

    
    
    
    
__u32 vsync_len; /* */ ……. };

    아래 아이콘 은 화면 전체 에 있 는 여러 가장자리 구역 의 위 치 를 표시 합 니 다.
 
  커 널 레벨 Fbinfo
C/C++ code

    
    
    
    
struct fb_info { int node; /* */ int flags; struct fb_var_screeninfo var; /* */ struct fb_fix_screeninfo fix; /* */ struct fb_monspecs monspecs; /* */ struct work_struct queue; /* */ struct fb_pixmap pixmap; /* */ struct fb_pixmap sprite; /* */ struct fb_cmap cmap; /* */ struct list_head modelist; /* */ struct fb_videomode * mode; /* */ ...... struct fb_ops * fbops; /* */ …… struct device * dev; /* */ …… char __iomem * screen_base; /* IO ( ) */ unsigned long screen_size; /* Amount of ioremapped VRAM or 0 */ void * pseudo_palette; /* */ …… };

     fb_info 는 디 스 플레이 구동 작업 의 주요 캐리어 로 현재 디 스 플레이 구동 과 콘 솔 에 관 한 모든 정 보 를 정의 합 니 다.디 스 플레이 구동 의 실현 형식 은 fb 를 초기 화 하 는 것 입 니 다.info 각 항목, LCD 컨트롤 러 설정 에 사용.이후 대부분의 작업 은 응용 층 이 ioctl 시스템 을 통 해 fb 를 호출 하 는 것 입 니 다.ops 의 함 수 는 fix, var 변수 중 값 을 얻 거나 수정 하여 레지스터 에 기록 합 니 다.팔레트 수정 등 작업.응용 층 에 표시 할 두 프레임 의 그림 에 사용 할 팔레트 가 다 르 면 fbops 의 함수 가 실현 되 고 후 자 는 팔레트 가 메모리 에 있 는 주 소 를 얻 으 며 그 중의 픽 셀 값 을 수정 하여 이 루어 집 니 다.
Fb_ops 안에 함수 포인터 가 많 습 니 다. 이런 함수 포인터 가 가리 키 는 것 은 보통 각 하드웨어 그래 픽 카드 가 자체 적 으로 가지 고 있 는 바 텀 구동 함수 입 니 다. 만약 에 독자 가 전문 적 인 그래 픽 카드 를 개발 하려 면 fbops 이 구조 에 서 는 반드시 포인터 로 이런 그래 픽 카드 전용 함수 들 을 열거 해 야 한다.우 리 는 그 중의 두 함수 지침 만 간단하게 소개 합 니 다.
C/C++ code

    
    
    
    
int ( * fb_check_var)( struct fb_var_screeninfo * var, struct fb_info * info);

     이 포인터 가 가리 키 는 함 수 는 앞에서 언급 한 가 변 디 스 플레이 파 라 메 터 를 검사 하 는 데 사 용 됩 니 다. 예 를 들 어 픽 셀 깊이, 가장자리 너비 또는 깊이 등 입 니 다.여기 있 는 인 자 는 수정 되 지 않 습 니 다.
    
C/C++ code

    
    
    
    
int ( * fb_set_par)( struct fb_info * info);

     여기 서 가리 키 는 함 수 는 표시 매개 변 수 를 실질 적 으로 수정 할 수 있 습 니 다.4 Frambuffer 구동 실현 프레임 워 크     여기 서 우 리 는 모두 가 이미 비교적 익숙 한 드라이버 등록 과 취소 두 과정 을 반복 하지 않 는 다.우 리 는 fbmem. c 의 몇 가지 중요 함 수 를 대상 으로 등록 후 로그아웃 하기 전에 프레임 버퍼 구동 의 대체적인 절 차 를 설명 합 니 다.fbmem. c 의 함 수 를 선택 한 이 유 는 이 파일 의 함수 가 일정한 대표 성 을 가지 기 때 문 입 니 다. 독자 들 은 그들의 대체적인 구 조 를 이해 한 후에 하 나 를 들 어 다른 구체 적 인 그래 픽 카드 의 드라이버 를 분석 하고 이해 할 수 있 습 니 다.     이 몇 개의 함 수 는 각각 fb 이다.mmap,fb_set_var 와 fbioctl。      Fb_mmap 는 말 그대로 장치 에서 시스템 메모리 (가상 주소) 사이 의 맵 을 완성 하 는 것 입 니 다.
C/C++ code

    
    
    
    
static int fb_mmap(struct file *file, struct vm_area_struct * vma)

    
    
    
    
{

    
    
    
    
int fbidx = iminor(file->f_path.dentry->d_inode); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops;

    
    
    
    
unsigned long off;

    
    
    
    
unsigned long start;

    
    
    
    
u32 len;

    
    
    
    
 

    
    
    
    
if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))

    
    
    
    
return -EINVAL;

    
    
    
    
off = vma->vm_pgoff << PAGE_SHIFT;

    
    
    
    
if (!fb)

    
    
    
    
return -ENODEV;

    
    
    
    
if (fb->fb_mmap) { // : mmap ,

    
    
    
    
int res;

    
    
    
    
lock_kernel(); //

    
    
    
    
res = fb->fb_mmap(info, vma); // mmap

    
    
    
    
unlock_kernel();

    
    
    
    
return res;

    
    
    
    
} lock_kernel(); start = info->fix.smem_start; // len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len); // if (off >= len) { /* I/O */ off -= len; if (info->var.accel_flags) { unlock_kernel(); return -EINVAL; } start = info->fix.mmio_start;// I/O len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len); } unlock_kernel(); start &= PAGE_MASK; if ((vma->vm_end - vma->vm_start + off) > len) // return -EINVAL; off += start; vma->vm_pgoff = off >> PAGE_SHIFT; /* IO , */ vma->vm_flags |= VM_IO | VM_RESERVED; fb_pgprotect(file, vma, off); // if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot)) // return -EAGAIN; return 0; }
 
  

     这里的映射行为发生在驱动程序初始化阶段。请注意,这些行为是否被囊括在一个名

为mmap的函数中并不是问题的关键,我们在开发中真正应该关心的是映射所需要的前提

条件如设备物理地址的提取,映射长度的确认以及实际的映射操作。只要在驱动程序的初

始化中完成了上述动作,那就算是成功了。因此,不少显卡的驱动程序里是找不到mmap

这个函数的,但它们一样工作得很好,原因就是它们已经完成了实际的映射操作。    

     下面我们看看fb_set_var函数。它主要完成了显示模式、可变参数的设置。

Fb_set_var这样的函数在不同的显示驱动中的具体名称也不一样,但基本上

的功能都是完成对于模式和可变参数的控制。某些系统的驱动里fb_set_var

是不含fb_check_var这样的函数的。

C/C++ code

    
    
    
    
int fb_set_var( struct fb_info * info, struct fb_var_screeninfo * var) { int flags = info -> flags; int ret = 0 ; ……. if ( ! info -> fbops -> fb_check_var) { * var = info -> var; goto done; } ret = info -> fbops -> fb_check_var(var, info); // if (ret) goto done; if ((var -> activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) { struct fb_videomode mode; …… info -> var = * var; if (info -> fbops -> fb_set_par) // fb_set_par info -> fbops -> fb_set_par(info); // fb_pan_display(info, & info -> var); // fb_set_cmap( & info -> cmap, info); // fb_var_to_videomode( & mode, & info -> var); // ...... } } } done: return ret; }

     Fb_ioctl 함 수 는 커 널 에서 디 스 플레이 장치 매개 변 수 를 읽 는 것 (가 변 적 이 고 고정 적 인 것 이 모두 있 음) 을 포함 하여 많은 기능 을 모 았 습 니 다. 매개 변 수 를 설정 하 는 것 (위 에서 언급 한 fb set var 함수 호출) 입 니 다.이러한 기능 은 일반적으로 분류 방면 의 제한 이 없 기 때문에 개발 자 는 각종 자신 이 실현 한 기능 을 모두 fb 에 넣 을 수 있다.ioctl 중.그리고 개발 자 들 도 시스템 이 제공 하 는 이 fb 를 완전히 버 릴 수 있다.ioctl 전환 자신의 fbioctl。
C/C++ code

    
    
    
    
static int fb_ioctl( struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { int fbidx = iminor(inode); struct fb_info * info = registered_fb[fbidx]; // struct fb_ops * fb = info -> fbops; // struct fb_var_screeninfo var; // struct fb_fix_screeninfo fix; // struct fb_con2fbmap con2fb; struct fb_cmap_user cmap; // struct fb_event event ; void __user * argp = ( void __user * )arg; int i; if ( ! fb) return - ENODEV; switch (cmd) { case FBIOGET_VSCREENINFO: return copy_to_user(argp, & info -> var, sizeof (var)) ? - EFAULT : 0 ; // case FBIOPUT_VSCREENINFO: if (copy_from_user( & var, argp, sizeof (var))) return - EFAULT; // acquire_console_sem(); // info -> flags |= FBINFO_MISC_USEREVENT; i = fb_set_var(info, & var); // info -> flags &= ~ FBINFO_MISC_USEREVENT; release_console_sem(); // if (i) return i; if (copy_to_user(argp, & var, sizeof (var))) return - EFAULT; return 0 ; case FBIOGET_FSCREENINFO: return copy_to_user(argp, & info -> fix, // sizeof (fix)) ? - EFAULT : 0 ; case FBIOPUTCMAP: // if (copy_from_user( & cmap, argp, sizeof (cmap))) return - EFAULT; return (fb_set_user_cmap( & cmap, info)); …… case FBIOBLANK: acquire_console_sem(); info -> flags |= FBINFO_MISC_USEREVENT; i = fb_blank(info, arg); // info -> flags &= ~ FBINFO_MISC_USEREVENT; release_console_sem(); return i; default : if (fb -> fb_ioctl == NULL) // fb_ioctl return - EINVAL; return fb -> fb_ioctl(info, cmd, arg); } }

     위의 서술 과정 에서 볼 수 있 듯 이 프레임 버퍼 드라이버 에 대해 서로 다른 디 스 플레이 장치 가 서로 다른 특정한 기능 을 가 질 수 있 지만 커 널 에 드라이버 를 등록 한 후에 실행 하 는 공통점 은 모두 물리 장치 와 가상 메모리 간 의 매 핑 (fb mmap) 을 먼저 해 야 한 다 는 것 이다.장 비 를 조작 하 는 과정 에서 fbset_var 는 설비 의 운행 매개 변 수 를 제어 할 수 있 기 때문에 특히 중요 하 다.유사 한 장치 매개 변수 읽 기와 쓰기 함수 그리고 fbcheck_var 등, 이 함수 들 은 일반적으로 fb 에 포 함 됩 니 다.ioctl 함수 에서 호출 되 었 습 니 다.상기 매개 변수의 조작 대상 은 바로 우리 가 지난 절 에 소개 한 fb 이다.info,fb_fix_screeninfo ,fb_var_screenfo 등 데이터 구조.

좋은 웹페이지 즐겨찾기