---restore content starts---
Framebuffer module Initialization process:--DRIVER\VIDEO\FBMEM.C
1. Initialize Framebuffer:
Framebuffer driver is registered in the form of a module in the system, when the module is initialized, create framebuffer corresponding device files and proc files, and register the framebuffer device operation interface function Fb_fops.
Static int__init Fbmem_init (void) {proc_create ("FB",0, NULL, &fb_proc_fops);///reporting driver status and parameters to the proc file system if(Register_chrdev (Fb_major,"FB", &fb_fops))///registered character device driver, the main device number isPrintk"unable to get major%d for FB devs\n", Fb_major); Fb_class= Class_create (This_module,"Graphics");///Create a/sys/class/graphics device class to build a device file with Mdev if(Is_err (Fb_class)) {PRINTK (kern_warning"Unable to create FB class; errno =%ld\n", Ptr_err (Fb_class)); Fb_class=NULL; } return 0;}
Framebuffer, as a subsystem, registers a character device driver with a master device number bit 29 in the Fbmem_init through the Register_chrdev interface. Create a graphics device class from Class_create, with the Mdev mechanism to generate device files for user access (located in the/dev directory).
2, framebuffer device-driven interface set FB_FOPS is defined as:
Static Const structFile_operations Fb_fops ={. Owner=this_module,. Read=Fb_read,. Write= Fb_write,//Two-time copy. Unlocked_ioctl =Fb_ioctl, #ifdef config_compat. Compat_ioctl=Fb_compat_ioctl,#endif. Mmap= Fb_mmap,///map, copy once. Open =Fb_open,. Release=fb_release, #ifdef have_arch_fb_unmapped_area. Get_unmapped_area=Get_fb_unmapped_area,#endif#ifdef config_fb_deferred_io. Fsync=Fb_deferred_io_fsync,#endif. Llseek=Default_llseek,};
In Linux device drivers, all display cache devices are managed internally by the Framebuffer subsystem, which means that the Linux device driver framework recognizes only one framebuffer device with a master device number of 29. Application tier All access to the display cache (up to 32) is pushed to Fb_fops for further distribution operations.
3, registration Framebuffer:
Linux provides the Register_framebuffer () and Unregister_framebuffer () functions, respectively, as registration and logoff framebuffer devices, both of which accept fb_info pointers as parameters, and the prototypes are:
int Register_framebuffer (struct fb_info *fb_info);
int Unregister_framebuffer (struct fb_info *fb_info);
For Register_framebuffer (), if the registered frame buffer device exceeds Fb_max (currently defined as 32), it is returned as-enxio, and the registered success is returned as 0.
int Register_framebuffer (struct fb_info *fb_info) { int ret; Mutex_lock (®istration_lock); = Do_register_framebuffer (fb_info); Mutex_unlock (®istration_lock); return ret;} Export_symbol (register_framebuffer); // The boot process of the kernel is called to perform the operation of the registered frame buffer hardware Device
Static int Do_register_framebuffer(structFb_info *fb_info) { intI, ret; structFb_eventEvent; structFb_videomode mode; if(Fb_check_foreignness (fb_info))return-Enosys; RET= Do_remove_conflicting_framebuffers (fb_info->Apertures, Fb_info-fix.id, Fb_is_primary_device (Fb_info)); if(ret)returnret; if(NUM_REGISTERED_FB = = Fb_max)//if the registered frame buffer device exceeds Fb_max (currently defined as 32), it is returned as-enxio, and the registered success is returned as 0. return-Enxio; NUM_REGISTERED_FB++;///number of frame buffers hardware devices already registered for(i =0; i < Fb_max; i++) if(!registered_fb[i])///Registered_fb[i] Save all registered frame buffers hardware devices Break; Fb_info->node =i; Atomic_set (&fb_info->count,1); Mutex_init (&fb_info->Lock); Mutex_init (&fb_info->Mm_lock); Fb_info->dev =device_create(Fb_class, Fb_info->device,///Create an FBX device under/sys/grapics/for device file creationMKDEV (Fb_major, i), NULL,"fb%d", i); if(Is_err (fb_info->Dev)) { /*Not fatal*/PRINTK (kern_warning"Unable to create device for framebuffer%d; errno =%ld\n", I, Ptr_err (fb_info->Dev)); Fb_info->dev =NULL; } ElseFb_init_device (Fb_info); if(Fb_info->pixmap.addr = =NULL) {Fb_info->PIXMAP.ADDR =Kmalloc (fbpixmapsize, Gfp_kernel); if(fb_info->pixmap.addr) {fb_info->pixmap.size =fbpixmapsize; Fb_info->pixmap.buf_align =1; Fb_info->pixmap.scan_align =1; Fb_info->pixmap.access_align = +; Fb_info->pixmap.flags =Fb_pixmap_default; }} fb_info->pixmap.offset =0; if(!fb_info->pixmap.blit_x) Fb_info->pixmap.blit_x = ~ (U32)0; if(!fb_info->pixmap.blit_y) Fb_info->pixmap.blit_y = ~ (U32)0; if(!fb_info->modelist.prev | |!fb_info->modelist.next) Init_list_head (&fb_info->modelist); if(fb_info->skip_vt_switch) pm_vt_switch_required (Fb_info->dev,false); Elsepm_vt_switch_required (Fb_info->dev,true); Fb_var_to_videomode (&mode, &fb_info->var); Fb_add_videomode (&mode, &fb_info->modelist); Registered_fb[i]=Fb_info; Event. info =Fb_info; Console_lock (); if(!Lock_fb_info (Fb_info)) {Console_unlock (); return-Enodev; } fb_notifier_call_chain (fb_event_fb_registered,&Event);///notifies the frame buffer console that a new frame buffer device is registered to the kernel .Unlock_fb_info (Fb_info); Console_unlock (); return 0;}
Each slave device needs to pass a FB_INFO data structure pointer, which represents a single display cache device. From there, you can see that fb_info will eventually be stored in the global array struct Fb_info*registered_fb[fb_max], Fb_max is 32, and from here we can see that Framebuffer supports up to 32 slave devices. In addition, each slave device registration also creates a device in the/sys/class/graphics/device class and eventually generates the corresponding device file in the/dev/directory by Mdev. If M calls the Register_framebuffer interface from a device, it generates m device files in/dev, such as/dev/fb0,/DEV/FB1,/DEV/FB2, and so on. The main device number of this m device is 29, from the device is 0, 1, 2 and so on.
Each registered frame buffer hardware device has a corresponding device file Fb<minor> in the/dev/graphics directory, where,<minor> represents a slave device number. For example, the first registered frame buffer hardware device has a corresponding device file fb0 in the/dev/graphics directory. User-space applications can manipulate the frame buffer hardware device through this device file, rendering the screen to be displayed to the frame buffer hardware device.
frame buffer console The corresponding driver module in the kernel is Fbcon: (DRIVERS\VIDEO\CONSOLE\FBCON.C)
Initialization
Static structNotifier_block Fbcon_event_notifier ={. Notifier_call= fbcon_event_notify,}; ......Static int__init Fb_console_init (void)//Frame Buffer Console initialization{ inti; Console_lock (); Fb_register_client (&Fbcon_event_notifier);//call Fb_register_client to listen for the frame buffer registration event for hardware devices, fbcon_event_notifier---> ImplementationFbcon_device = Device_create (Fb_class, NULL, MKDEV (0,0), NULL,"Fbcon"); if(Is_err (Fbcon_device)) {PRINTK (kern_warning"Unable to create device" "For fbcon; errno =%ld\n", Ptr_err (Fbcon_device)); Fbcon_device=NULL; } ElseFbcon_init_device (); for(i =0; i < max_nr_consoles; i++) Con2fb_map[i]= -1; Console_unlock (); Fbcon_start (); return 0;}
This function, in addition to calling function Device_create to create a device Fbcon class graphics, also calls the function fb_register_client to listen for the registration events of the frame buffer hardware device, which is the function Fbcon_event_ Notify is implemented as follows:
Static intFbcon_event_notify (structNotifier_block *Self , unsignedLongActionvoid*data) { structFb_event *Event=data; structFb_info *info =Event-info; structFb_videomode *mode; structFb_con2fbmap *CON2FB; structFb_blit_caps *caps; intIDX, ret =0; Switch(action) {... CaseFb_event_fb_registered:ret= fbcon_fb_registered (info);///---> Frame buffers the registration events for hardware devices are ultimately handled by the function fbcon_fb_registered . Break; ....... } Done:returnret;}
The registration event for the frame buffer hardware device is ultimately handled by the function fbcon_fb_registered, and its implementation is as follows:
Static intFbcon_fb_registered (structFb_info *info) { intRET =0, I, IDX; IDX= info->node; Fbcon_select_primary (info);///Check whether the currently registered frame buffer hardware device is a primary frame buffer hardware device, and if so, record its information if(Info_idx = =-1) {///if so, record its information. for(i = FIRST_FB_VC; I <= LAST_FB_VC; i++) { if(Con2fb_map_boot[I] = =idx) {Info_idx=idx; Break; } } if(Info_idx! =-1) ret= Do_fbcon_takeover (1); } Else { for(i = FIRST_FB_VC; I <= LAST_FB_VC; i++) { if(Con2fb_map_boot[i] = =idx) set_con2fb_map(i, IDX,0); } } returnret;}
The function fbcon_select_primary is used to check whether the currently registered frame buffer hardware device is a primary frame buffer hardware device. If so, record its information. This function is only valid if the config_framebuffer_console_detect_primary compilation option is specified, otherwise it is an empty function.
In the Linux kernel, each console and each frame buffer hardware device has a number starting from 0, and their initial correspondence is saved in the global array con2fb_map_boot . The initial correspondence between the console and the frame buffer hardware device can be initialized by setting the kernel boot parameters. In module Fbcon, there is another global array con2fb_map, which is also used to map the corresponding relationship between the console and the frame buffer hardware device, but it maps the actual correspondence between the console and the frame buffer hardware device.
---restore content ends---
Framebuffer Driving Learning Summary (ii)----Framebuffer module initialization