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

📄 fbcon.c

📁 h内核
💻 C
📖 第 1 页 / 共 5 页
字号:
#elsestatic void set_blitting_type(struct vc_data *vc, struct fb_info *info,			      struct display *p){	struct fbcon_ops *ops = info->fbcon_par;	info->flags &= ~FBINFO_MISC_TILEBLITTING;	fbcon_set_bitops(ops);}#endif /* CONFIG_MISC_TILEBLITTING */static int con2fb_acquire_newinfo(struct vc_data *vc, struct fb_info *info,				  int unit, int oldidx){	struct fbcon_ops *ops = NULL;	int err = 0;	if (!try_module_get(info->fbops->owner))		err = -ENODEV;	if (!err && info->fbops->fb_open &&	    info->fbops->fb_open(info, 0))		err = -ENODEV;	if (!err) {		ops = kmalloc(sizeof(struct fbcon_ops), GFP_KERNEL);		if (!ops)			err = -ENOMEM;	}	if (!err) {		memset(ops, 0, sizeof(struct fbcon_ops));		info->fbcon_par = ops;		set_blitting_type(vc, info, NULL);	}	if (err) {		con2fb_map[unit] = oldidx;		module_put(info->fbops->owner);	}	return err;}static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo,				  struct fb_info *newinfo, int unit,				  int oldidx, int found){	struct fbcon_ops *ops = oldinfo->fbcon_par;	int err = 0;	if (oldinfo->fbops->fb_release &&	    oldinfo->fbops->fb_release(oldinfo, 0)) {		con2fb_map[unit] = oldidx;		if (!found && newinfo->fbops->fb_release)			newinfo->fbops->fb_release(newinfo, 0);		if (!found)			module_put(newinfo->fbops->owner);		err = -ENODEV;	}	if (!err) {		if (oldinfo->queue.func == fb_flashcursor)			del_timer_sync(&ops->cursor_timer);		kfree(ops->cursor_state.mask);		kfree(ops->cursor_data);		kfree(oldinfo->fbcon_par);		oldinfo->fbcon_par = NULL;		module_put(oldinfo->fbops->owner);	}	return err;}static void con2fb_init_newinfo(struct fb_info *info){	if (!info->queue.func || info->queue.func == fb_flashcursor) {		struct fbcon_ops *ops = info->fbcon_par;		if (!info->queue.func)			INIT_WORK(&info->queue, fb_flashcursor, info);		init_timer(&ops->cursor_timer);		ops->cursor_timer.function = cursor_timer_handler;		ops->cursor_timer.expires = jiffies + HZ / 5;		ops->cursor_timer.data = (unsigned long ) info;		add_timer(&ops->cursor_timer);	}}static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,				int unit, int show_logo){	struct fbcon_ops *ops = info->fbcon_par;	ops->currcon = fg_console;	if (info->fbops->fb_set_par)		info->fbops->fb_set_par(info);	if (vc)		fbcon_set_disp(info, vc);	else		fbcon_preset_disp(info, unit);	if (show_logo) {		struct vc_data *fg_vc = vc_cons[fg_console].d;		struct fb_info *fg_info =			registered_fb[con2fb_map[fg_console]];		fbcon_prepare_logo(fg_vc, fg_info, fg_vc->vc_cols,				   fg_vc->vc_rows, fg_vc->vc_cols,				   fg_vc->vc_rows);	}	switch_screen(fg_console);}/** *	set_con2fb_map - map console to frame buffer device *	@unit: virtual console number to map *	@newidx: frame buffer index to map virtual console to *      @user: user request * *	Maps a virtual console @unit to a frame buffer device *	@newidx. */static int set_con2fb_map(int unit, int newidx, int user){	struct vc_data *vc = vc_cons[unit].d;	int oldidx = con2fb_map[unit];	struct fb_info *info = registered_fb[newidx];	struct fb_info *oldinfo = NULL; 	int found, err = 0;	if (oldidx == newidx)		return 0;	if (!info) 		err =  -EINVAL; 	if (!err && !search_for_mapped_con()) {		info_idx = newidx;		return fbcon_takeover(0);	}	if (oldidx != -1)		oldinfo = registered_fb[oldidx];	found = search_fb_in_map(newidx);	acquire_console_sem();	con2fb_map[unit] = newidx;	if (!err && !found) 		err = con2fb_acquire_newinfo(vc, info, unit, oldidx);	/*	 * If old fb is not mapped to any of the consoles,	 * fbcon should release it.	 */ 	if (!err && oldinfo && !search_fb_in_map(oldidx)) 		err = con2fb_release_oldinfo(vc, oldinfo, info, unit, oldidx, 					     found); 	if (!err) { 		int show_logo = (fg_console == 0 && !user && 				 logo_shown != FBCON_LOGO_DONTSHOW); 		if (!found) 			con2fb_init_newinfo(info); 		con2fb_map_boot[unit] = newidx; 		con2fb_init_display(vc, info, unit, show_logo);	}	release_console_sem(); 	return err;}/* *  Low Level Operations *//* NOTE: fbcon cannot be __init: it may be called from take_over_console later */static int var_to_display(struct display *disp,			  struct fb_var_screeninfo *var,			  struct fb_info *info){	disp->xres_virtual = var->xres_virtual;	disp->yres_virtual = var->yres_virtual;	disp->bits_per_pixel = var->bits_per_pixel;	disp->grayscale = var->grayscale;	disp->nonstd = var->nonstd;	disp->accel_flags = var->accel_flags;	disp->height = var->height;	disp->width = var->width;	disp->red = var->red;	disp->green = var->green;	disp->blue = var->blue;	disp->transp = var->transp;	disp->mode = fb_match_mode(var, &info->modelist);	if (disp->mode == NULL)		/* This should not happen */		return -EINVAL;	return 0;}static void display_to_var(struct fb_var_screeninfo *var,			   struct display *disp){	fb_videomode_to_var(var, disp->mode);	var->xres_virtual = disp->xres_virtual;	var->yres_virtual = disp->yres_virtual;	var->bits_per_pixel = disp->bits_per_pixel;	var->grayscale = disp->grayscale;	var->nonstd = disp->nonstd;	var->accel_flags = disp->accel_flags;	var->height = disp->height;	var->width = disp->width;	var->red = disp->red;	var->green = disp->green;	var->blue = disp->blue;	var->transp = disp->transp;}static const char *fbcon_startup(void){	const char *display_desc = "frame buffer device";	struct display *p = &fb_display[fg_console];	struct vc_data *vc = vc_cons[fg_console].d;	struct font_desc *font = NULL;	struct module *owner;	struct fb_info *info = NULL;	struct fbcon_ops *ops;	int rows, cols;	int irqres;	irqres = 1;	/*	 *  If num_registered_fb is zero, this is a call for the dummy part.	 *  The frame buffer devices weren't initialized yet.	 */	if (!num_registered_fb || info_idx == -1)		return display_desc;	/*	 * Instead of blindly using registered_fb[0], we use info_idx, set by	 * fb_console_init();	 */	info = registered_fb[info_idx];	if (!info)		return NULL;		owner = info->fbops->owner;	if (!try_module_get(owner))		return NULL;	if (info->fbops->fb_open && info->fbops->fb_open(info, 0)) {		module_put(owner);		return NULL;	}	ops = kmalloc(sizeof(struct fbcon_ops), GFP_KERNEL);	if (!ops) {		module_put(owner);		return NULL;	}	memset(ops, 0, sizeof(struct fbcon_ops));	ops->currcon = -1;	info->fbcon_par = ops;	set_blitting_type(vc, info, NULL);	if (info->fix.type != FB_TYPE_TEXT) {		if (fbcon_softback_size) {			if (!softback_buf) {				softback_buf =				    (unsigned long)				    kmalloc(fbcon_softback_size,					    GFP_KERNEL);				if (!softback_buf) {					fbcon_softback_size = 0;					softback_top = 0;				}			}		} else {			if (softback_buf) {				kfree((void *) softback_buf);				softback_buf = 0;				softback_top = 0;			}		}		if (softback_buf)			softback_in = softback_top = softback_curr =			    softback_buf;		softback_lines = 0;	}	/* Setup default font */	if (!p->fontdata) {		if (!fontname[0] || !(font = find_font(fontname)))			font = get_default_font(info->var.xres,						info->var.yres);		vc->vc_font.width = font->width;		vc->vc_font.height = font->height;		vc->vc_font.data = p->fontdata = font->data;		vc->vc_font.charcount = 256; /* FIXME  Need to support more fonts */	}	cols = info->var.xres / vc->vc_font.width;	rows = info->var.yres / vc->vc_font.height;	vc_resize(vc->vc_num, cols, rows);	DPRINTK("mode:   %s\n", info->fix.id);	DPRINTK("visual: %d\n", info->fix.visual);	DPRINTK("res:    %dx%d-%d\n", info->var.xres,		info->var.yres,		info->var.bits_per_pixel);#ifdef CONFIG_ATARI	if (MACH_IS_ATARI) {		cursor_blink_rate = ATARI_CURSOR_BLINK_RATE;		irqres =		    request_irq(IRQ_AUTO_4, fb_vbl_handler,				IRQ_TYPE_PRIO, "framebuffer vbl",				info);	}#endif				/* CONFIG_ATARI */#ifdef CONFIG_MAC	/*	 * On a Macintoy, the VBL interrupt may or may not be active. 	 * As interrupt based cursor is more reliable and race free, we 	 * probe for VBL interrupts.	 */	if (MACH_IS_MAC) {		int ct = 0;		/*		 * Probe for VBL: set temp. handler ...		 */		irqres = request_irq(IRQ_MAC_VBL, fb_vbl_detect, 0,				     "framebuffer vbl", info);		vbl_detected = 0;		/*		 * ... and spin for 20 ms ...		 */		while (!vbl_detected && ++ct < 1000)			udelay(20);		if (ct == 1000)			printk			    ("fbcon_startup: No VBL detected, using timer based cursor.\n");		free_irq(IRQ_MAC_VBL, fb_vbl_detect);		if (vbl_detected) {			/*			 * interrupt based cursor ok			 */			cursor_blink_rate = MAC_CURSOR_BLINK_RATE;			irqres =			    request_irq(IRQ_MAC_VBL, fb_vbl_handler, 0,					"framebuffer vbl", info);		} else {			/*			 * VBL not detected: fall through, use timer based cursor			 */			irqres = 1;		}	}#endif				/* CONFIG_MAC */#if defined(__arm__) && defined(IRQ_VSYNCPULSE)	cursor_blink_rate = ARM_CURSOR_BLINK_RATE;	irqres = request_irq(IRQ_VSYNCPULSE, fb_vbl_handler, SA_SHIRQ,			     "framebuffer vbl", info);#endif	/* Initialize the work queue. If the driver provides its	 * own work queue this means it will use something besides 	 * default timer to flash the cursor. */	if (!info->queue.func) {		INIT_WORK(&info->queue, fb_flashcursor, info);		init_timer(&ops->cursor_timer);		ops->cursor_timer.function = cursor_timer_handler;		ops->cursor_timer.expires = jiffies + HZ / 5;		ops->cursor_timer.data = (unsigned long ) info;		add_timer(&ops->cursor_timer);	}	return display_desc;}static void fbcon_init(struct vc_data *vc, int init){	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];	struct vc_data **default_mode = vc->vc_display_fg;	struct vc_data *svc = *default_mode;	struct display *t, *p = &fb_display[vc->vc_num];	int display_fg = (*default_mode)->vc_num;	int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256;	int cap = info->flags;	if (info_idx == -1 || info == NULL)	    return;	if (vc->vc_num != display_fg || logo_shown == FBCON_LOGO_DONTSHOW ||	    (info->fix.type == FB_TYPE_TEXT))		logo = 0;	info->var.xoffset = info->var.yoffset = p->yscroll = 0;	/* reset wrap/pan */	if (var_to_display(p, &info->var, info))		return;	/* If we are not the first console on this	   fb, copy the font from that console */	t = &fb_display[display_fg];	if (!vc->vc_font.data) {		vc->vc_font.data = p->fontdata = t->fontdata;		vc->vc_font.width = (*default_mode)->vc_font.width;		vc->vc_font.height = (*default_mode)->vc_font.height;		p->userfont = t->userfont;		if (p->userfont)			REFCOUNT(p->fontdata)++;	}	if (p->userfont)		charcnt = FNTCHARCNT(p->fontdata);	vc->vc_can_do_color = (fb_get_color_depth(info) != 1);	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;	if (charcnt == 256) {		vc->vc_hi_font_mask = 0;	} else {		vc->vc_hi_font_mask = 0x100;		if (vc->vc_can_do_color)			vc->vc_complement_mask <<= 1;	}	if (!*svc->vc_uni_pagedir_loc)		con_set_default_unimap(display_fg);	if (!*vc->vc_uni_pagedir_loc)		con_copy_unimap(vc->vc_num, display_fg);	cols = vc->vc_cols;	rows = vc->vc_rows;	new_cols = info->var.xres / vc->vc_font.width;	new_rows = info->var.yres / vc->vc_font.height;	vc_resize(vc->vc_num, new_cols, new_rows);	/*	 * We must always set the mode. The mode of the previous console	 * driver could be in the same resolution but we are using different	 * hardware so we have to initialize the hardware.	 *	 * We need to do it in fbcon_init() to prevent screen corruption.	 */	if (CON_IS_VISIBLE(vc) && info->fbops->fb_set_par)		info->fbops->fb_set_par(info);	if ((cap & FBINFO_HWACCEL_COPYAREA) &&	    !(cap & FBINFO_HWACCEL_DISABLED))		p->scrollmode = SCROLL_MOVE;	else /* default to something safe */		p->scrollmode = SCROLL_REDRAW;	/*	 *  ++guenther: console.c:vc_allocate() relies on initializing	 *  vc_{cols,rows}, but we must not set those if we are only	 *  resizing the console.	 */	if (!init) {		vc->vc_cols = new_cols;		vc->vc_rows = new_rows;	}	if (logo)		fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);	if (vc->vc_num == display_fg && softback_buf) {		int l = fbcon_softback_size / vc->vc_size_row;		if (l > 5)			softback_end = softback_buf + l * vc->vc_size_row;		else {			/* Smaller scrollback makes no sense, and 0 would screw			   the operation totally */			softback_top = 0;		}	}}static void fbcon_deinit(struct vc_data *vc){	struct display *p = &fb_display[vc->vc_num];	if (info_idx != -1)	    return;

⌨️ 快捷键说明

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