The advanced driver courses over the past few days are really happy. Block devices and MTD devices are really clear and open-minded.
When it's still hot and free, record the MMAP implementation in the S3C2410 framebuffer driver. For more information, see
Previously, MMAP was replaced. There is no concept of how to implement an MMAP in the kernel space.
There is no MMAP implementation in fb_ops in s3c2410fb. C. FB is a veteran device driver and has evolved into a sub-system. Therefore, the lack of implementation is in higher-level code.
S3c2410fb. C-"s3c24xxfb_probe-" s3c2410fb_map_video_memory-"
Info-> screen_base = dma_alloc_writecombine (FBI-> Dev, map_size, & map_dma, gfp_kernel );
Info-> fix. smem_start = map_dma;
A physical memory is obtained from the DMA memory space, and the physical starting address is located in map_dma.
Info-> screen_base is a virtual address but belongs to the kernel space.
Then in fbmem. C,
Static int
Fb_mmap (struct file * file, struct vm_area_struct * VMA)
_ Acquires (& info-> lock)
_ Releases (& info-> lock)
{
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_mmap is implemented in fb_ops, you can call the user-implemented fb_mmap. As mentioned above, this is not implemented here.
If (FB-> fb_mmap ){
Int res;
Mutex_lock (& info-> lock );
Res = FB-> fb_mmap (Info, VMA );
Mutex_unlock (& info-> lock );
Return res;
}
Mutex_lock (& info-> lock );
/* Frame Buffer Memory */
Start = Info-> fix. smem_start;
// The start address is page aligned.
Len = page_align (Start &~ Page_mask) + Info-> fix. smem_len );
// The off meaning in MMAP varies with the specific driver.
// Video card devices are often used to directly map the video card registers to the user space for acceleration.
If (Off> = Len ){
/* Memory mapped Io */
Off-= Len;
If (Info-> var. accel_flags ){
Mutex_unlock (& info-> lock );
Return-einval;
}
Start = Info-> fix. mmio_start;
Len = page_align (Start &~ Page_mask) + Info-> fix. mmio_len );
}
Mutex_unlock (& info-> lock );
Start & = page_mask;
If (VMA-> vm_end-VMA-> vm_start + off)> Len)
Return-einval;
Off + = start;
// Specify the Memory attribute of this segment
VMA-> vm_pgoff = off> page_shift;
/* This is an IO map-Tell maydump to skip this VMA */
VMA-> vm_flags | = vm_io | vm_reserved;
Fb_pgprotect (file, VMA, off );
// Formally map physical memory to user space virtual address
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;
}
Reference: http://hi.baidu.com/deep_pro/blog/item/4d5f2003122d3b83d53f7c73.html