⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fbmem.c

📁 《linux驱动程序设计从入门到精通》一书中所有的程序代码含驱动和相应的应用程序
💻 C
📖 第 1 页 / 共 3 页
字号:
			fb_pan_display(info, &info->var);			fb_set_cmap(&info->cmap, info);			if (info->flags & FBINFO_MISC_MODECHANGEUSER) {				info->flags &= ~FBINFO_MISC_MODECHANGEUSER;				notifier_call_chain(&fb_notifier_list,						    FB_EVENT_MODE_CHANGE, info);			}		}	}	return 0;}intfb_blank(struct fb_info *info, int blank){		/* ??? Variable sized stack allocation.  */	u16 black[info->cmap.len];	struct fb_cmap cmap;		if (info->fbops->fb_blank && !info->fbops->fb_blank(blank, info))		return 0;	if (blank) { 		memset(black, 0, info->cmap.len * sizeof(u16));		cmap.red = cmap.green = cmap.blue = black;		cmap.transp = info->cmap.transp ? black : NULL;		cmap.start = info->cmap.start;		cmap.len = info->cmap.len;	} else		cmap = info->cmap;	return fb_set_cmap(&cmap, info);}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;#ifdef CONFIG_FRAMEBUFFER_CONSOLE	struct fb_con2fbmap con2fb;#endif	struct fb_cmap_user cmap;	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_MODECHANGEUSER;		i = fb_set_var(info, &var);		info->flags &= ~FBINFO_MISC_MODECHANGEUSER;		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 FBIOGETCMAP:		if (copy_from_user(&cmap, argp, sizeof(cmap)))			return -EFAULT;		return fb_cmap_to_user(&info->cmap, &cmap);	case FBIOPAN_DISPLAY:		if (copy_from_user(&var, argp, sizeof(var)))			return -EFAULT;		acquire_console_sem();		i = fb_pan_display(info, &var);		release_console_sem();		if (i)			return i;		if (copy_to_user(argp, &var, sizeof(var)))			return -EFAULT;		return 0;	case FBIO_CURSOR:		acquire_console_sem();		i = fb_cursor(info, argp);		release_console_sem();		return i;#ifdef CONFIG_FRAMEBUFFER_CONSOLE	case FBIOGET_CON2FBMAP:		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))			return -EFAULT;		if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)		    return -EINVAL;		con2fb.framebuffer = con2fb_map[con2fb.console-1];		return copy_to_user(argp, &con2fb,				    sizeof(con2fb)) ? -EFAULT : 0;	case FBIOPUT_CON2FBMAP:		if (copy_from_user(&con2fb, argp, sizeof(con2fb)))			return - EFAULT;		if (con2fb.console < 0 || con2fb.console > MAX_NR_CONSOLES)		    return -EINVAL;		if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)		    return -EINVAL;#ifdef CONFIG_KMOD		if (!registered_fb[con2fb.framebuffer])		    try_to_load(con2fb.framebuffer);#endif /* CONFIG_KMOD */		if (!registered_fb[con2fb.framebuffer])		    return -EINVAL;		if (con2fb.console > 0 && con2fb.console < MAX_NR_CONSOLES)			return set_con2fb_map(con2fb.console-1,					      con2fb.framebuffer);		return -EINVAL;#endif	/* CONFIG_FRAMEBUFFER_CONSOLE */	case FBIOBLANK:		acquire_console_sem();		i = fb_blank(info, arg);		release_console_sem();		return i;	default:		if (fb->fb_ioctl == NULL)			return -EINVAL;		return fb->fb_ioctl(inode, file, cmd, arg, info);	}}static int fb_mmap(struct file *file, struct vm_area_struct * vma){	int fbidx = iminor(file->f_dentry->d_inode);	struct fb_info *info = registered_fb[fbidx];	struct fb_ops *fb = info->fbops;	unsigned long off;#if !defined(__sparc__) || defined(__sparc_v9__)	unsigned long start;	u32 len;#endif	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))		return -EINVAL;	off = vma->vm_pgoff << PAGE_SHIFT;	if (!fb)		return -ENODEV;	if (fb->fb_mmap) {		int res;		lock_kernel();		res = fb->fb_mmap(info, file, vma);		unlock_kernel();		return res;	}#if defined(__sparc__) && !defined(__sparc_v9__)	/* Should never get here, all fb drivers should have their own	   mmap routines */	return -EINVAL;#else	/* !sparc32... */	lock_kernel();	/* frame buffer memory */	start = info->fix.smem_start;	len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);	if (off >= len) {		/* memory mapped io */		off -= len;		if (info->var.accel_flags) {			unlock_kernel();			return -EINVAL;		}		start = info->fix.mmio_start;		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;	/* This is an IO map - tell maydump to skip this VMA */	vma->vm_flags |= VM_IO;#if defined(__sparc_v9__)	vma->vm_flags |= (VM_SHM | VM_LOCKED);	if (io_remap_page_range(vma, vma->vm_start, off,				vma->vm_end - vma->vm_start, vma->vm_page_prot, 0))		return -EAGAIN;#else#if defined(__mc68000__)#if defined(CONFIG_SUN3)	pgprot_val(vma->vm_page_prot) |= SUN3_PAGE_NOCACHE;#elif defined(CONFIG_MMU)	if (CPU_IS_020_OR_030)		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE030;	if (CPU_IS_040_OR_060) {		pgprot_val(vma->vm_page_prot) &= _CACHEMASK040;		/* Use no-cache mode, serialized */		pgprot_val(vma->vm_page_prot) |= _PAGE_NOCACHE_S;	}#endif#elif defined(__powerpc__)	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;#elif defined(__alpha__)	/* Caching is off in the I/O space quadrant by design.  */#elif defined(__i386__) || defined(__x86_64__)	if (boot_cpu_data.x86 > 3)		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;#elif defined(__mips__)	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);#elif defined(__hppa__)	pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;#elif defined(__ia64__) || defined(__arm__) || defined(__sh__)	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);#else#warning What do we have to do here??#endif	if (io_remap_page_range(vma, vma->vm_start, off,			     vma->vm_end - vma->vm_start, vma->vm_page_prot))		return -EAGAIN;#endif /* !__sparc_v9__ */	return 0;#endif /* !sparc32 */}static intfb_open(struct inode *inode, struct file *file){	int fbidx = iminor(inode);	struct fb_info *info;	int res = 0;	if (fbidx >= FB_MAX)		return -ENODEV;#ifdef CONFIG_KMOD	if (!(info = registered_fb[fbidx]))		try_to_load(fbidx);#endif /* CONFIG_KMOD */	if (!(info = registered_fb[fbidx]))		return -ENODEV;	if (!try_module_get(info->fbops->owner))		return -ENODEV;	if (info->fbops->fb_open) {		res = info->fbops->fb_open(info,1);		if (res)			module_put(info->fbops->owner);	}	return res;}static int fb_release(struct inode *inode, struct file *file){	int fbidx = iminor(inode);	struct fb_info *info;	lock_kernel();	info = registered_fb[fbidx];	if (info->fbops->fb_release)		info->fbops->fb_release(info,1);	module_put(info->fbops->owner);	unlock_kernel();	return 0;}static struct file_operations fb_fops = {	.owner =	THIS_MODULE,	.read =		fb_read,	.write =	fb_write,	.ioctl =	fb_ioctl,	.mmap =		fb_mmap,	.open =		fb_open,	.release =	fb_release,#ifdef HAVE_ARCH_FB_UNMAPPED_AREA	.get_unmapped_area = get_fb_unmapped_area,#endif};static struct class_simple *fb_class;/** *	register_framebuffer - registers a frame buffer device *	@fb_info: frame buffer info structure * *	Registers a frame buffer device @fb_info. * *	Returns negative errno on error, or zero for success. * */intregister_framebuffer(struct fb_info *fb_info){	int i;	struct class_device *c;	if (num_registered_fb == FB_MAX)		return -ENXIO;	num_registered_fb++;	for (i = 0 ; i < FB_MAX; i++)		if (!registered_fb[i])			break;	fb_info->node = i;	c = class_simple_device_add(fb_class, MKDEV(FB_MAJOR, i), NULL, "fb%d", i);	if (IS_ERR(c)) {		/* Not fatal */		printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(c));	}		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 = 4;			fb_info->pixmap.flags = FB_PIXMAP_DEFAULT;		}	}		fb_info->pixmap.offset = 0;	if (fb_info->sprite.addr == NULL) {		fb_info->sprite.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);		if (fb_info->sprite.addr) {			fb_info->sprite.size = FBPIXMAPSIZE;			fb_info->sprite.buf_align = 1;			fb_info->sprite.scan_align = 1;			fb_info->sprite.access_align = 4;			fb_info->sprite.flags = FB_PIXMAP_DEFAULT;		}	}	fb_info->sprite.offset = 0;	registered_fb[i] = fb_info;	devfs_mk_cdev(MKDEV(FB_MAJOR, i),			S_IFCHR | S_IRUGO | S_IWUGO, "fb/%d", i);	return 0;}/** *	unregister_framebuffer - releases a frame buffer device *	@fb_info: frame buffer info structure * *	Unregisters a frame buffer device @fb_info. * *	Returns negative errno on error, or zero for success. * */intunregister_framebuffer(struct fb_info *fb_info){	int i;	i = fb_info->node;	if (!registered_fb[i])		return -EINVAL;	devfs_remove("fb/%d", i);	if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))		kfree(fb_info->pixmap.addr);	if (fb_info->sprite.addr && (fb_info->sprite.flags & FB_PIXMAP_DEFAULT))		kfree(fb_info->sprite.addr);	registered_fb[i]=NULL;	num_registered_fb--;	class_simple_device_remove(MKDEV(FB_MAJOR, i));	return 0;}/** *	fb_register_client - register a client notifier *	@nb: notifier block to callback on events */int fb_register_client(struct notifier_block *nb){	return notifier_chain_register(&fb_notifier_list, nb);}/** *	fb_unregister_client - unregister a client notifier *	@nb: notifier block to callback on events */int fb_unregister_client(struct notifier_block *nb){	return notifier_chain_unregister(&fb_notifier_list, nb);}/** *	fb_set_suspend - low level driver signals suspend *	@info: framebuffer affected *	@state: 0 = resuming, !=0 = suspending * *	This is meant to be used by low level drivers to * 	signal suspend/resume to the core & clients. *	It must be called with the console semaphore held */void fb_set_suspend(struct fb_info *info, int state){	if (state) {		notifier_call_chain(&fb_notifier_list, FB_EVENT_SUSPEND, info);		info->state = FBINFO_STATE_SUSPENDED;	} else {		info->state = FBINFO_STATE_RUNNING;		notifier_call_chain(&fb_notifier_list, FB_EVENT_RESUME, info);	}}/** *	fbmem_init - init frame buffer subsystem * *	Initialize the frame buffer subsystem. * *	NOTE: This function is _only_ to be called by drivers/char/mem.c. * */void __init fbmem_init(void){	int i;	create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL);	devfs_mk_dir("fb");	if (register_chrdev(FB_MAJOR,"fb",&fb_fops))		printk("unable to get major %d for fb devs\n", FB_MAJOR);	fb_class = class_simple_create(THIS_MODULE, "graphics");	if (IS_ERR(fb_class)) {		printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));		fb_class = NULL;	}#ifdef CONFIG_FB_OF	if (ofonly) {		offb_init();		return;	}#endif	/*	 *  Probe for all builtin frame buffer devices	 */	for (i = 0; i < num_pref_init_funcs; i++)		pref_init_funcs[i]();	for (i = 0; i < NUM_FB_DRIVERS; i++)		if (fb_drivers[i].init)			fb_drivers[i].init();}/** *	video_setup - process command line options *	@options: string of options * *	Process command line options for frame buffer subsystem. * *	NOTE: This function is a __setup and __init function. * *	Returns zero. * */int __init video_setup(char *options){	int i, j;	if (!options || !*options)		return 0;	   #ifdef CONFIG_FB_OF	if (!strcmp(options, "ofonly")) {		ofonly = 1;		return 0;	}#endif	if (num_pref_init_funcs == FB_MAX)		return 0;	for (i = 0; i < NUM_FB_DRIVERS; i++) {		j = strlen(fb_drivers[i].name);		if (!strncmp(options, fb_drivers[i].name, j) &&			options[j] == ':') {			if (!strcmp(options+j+1, "off"))				fb_drivers[i].init = NULL;			else {				if (fb_drivers[i].init) {					pref_init_funcs[num_pref_init_funcs++] =						fb_drivers[i].init;					fb_drivers[i].init = NULL;				}				if (fb_drivers[i].setup)					fb_drivers[i].setup(options+j+1);			}			return 0;		}	}	/*	 * If we get here no fb was specified.	 * We consider the argument to be a global video mode option.	 */	global_mode_option = options;	return 0;}__setup("video=", video_setup);    /*     *  Visible symbols for modules     */EXPORT_SYMBOL(register_framebuffer);EXPORT_SYMBOL(unregister_framebuffer);EXPORT_SYMBOL(num_registered_fb);EXPORT_SYMBOL(registered_fb);EXPORT_SYMBOL(fb_prepare_logo);EXPORT_SYMBOL(fb_show_logo);EXPORT_SYMBOL(fb_set_var);EXPORT_SYMBOL(fb_blank);EXPORT_SYMBOL(fb_pan_display);EXPORT_SYMBOL(fb_get_buffer_offset);EXPORT_SYMBOL(fb_iomove_buf_unaligned);EXPORT_SYMBOL(fb_iomove_buf_aligned);EXPORT_SYMBOL(fb_sysmove_buf_unaligned);EXPORT_SYMBOL(fb_sysmove_buf_aligned);EXPORT_SYMBOL(fb_load_cursor_image);EXPORT_SYMBOL(fb_set_suspend);EXPORT_SYMBOL(fb_register_client);EXPORT_SYMBOL(fb_unregister_client);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -