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

📄 fbcon.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			options += 3;			if (*options)				first_fb_vc = simple_strtoul(options, &options, 10) - 1;			if (first_fb_vc < 0)				first_fb_vc = 0;			if (*options++ == '-')				last_fb_vc = simple_strtoul(options, &options, 10) - 1;			fbcon_is_default = 0; 		}			if (!strncmp(options, "rotate:", 7)) {			options += 7;			if (*options)				rotate = simple_strtoul(options, &options, 0);			if (rotate > 3)				rotate = 0;		}	}	return 0;}__setup("fbcon=", fb_console_setup);#endifstatic int search_fb_in_map(int idx){	int i, retval = 0;	for (i = 0; i < MAX_NR_CONSOLES; i++) {		if (con2fb_map[i] == idx)			retval = 1;	}	return retval;}static int search_for_mapped_con(void){	int i, retval = 0;	for (i = 0; i < MAX_NR_CONSOLES; i++) {		if (con2fb_map[i] != -1)			retval = 1;	}	return retval;}static int fbcon_takeover(int show_logo){	int err, i;	if (!num_registered_fb)		return -ENODEV;	if (!show_logo)		logo_shown = FBCON_LOGO_DONTSHOW;	for (i = first_fb_vc; i <= last_fb_vc; i++)		con2fb_map[i] = info_idx;	err = take_over_console(&fb_con, first_fb_vc, last_fb_vc,				fbcon_is_default);	if (err) {		for (i = first_fb_vc; i <= last_fb_vc; i++) {			con2fb_map[i] = -1;		}		info_idx = -1;	}	return err;}static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,			       int cols, int rows, int new_cols, int new_rows){	/* Need to make room for the logo */	struct fbcon_ops *ops = info->fbcon_par;	int cnt, erase = vc->vc_video_erase_char, step;	unsigned short *save = NULL, *r, *q;	/*	 * remove underline attribute from erase character	 * if black and white framebuffer.	 */	if (fb_get_color_depth(&info->var, &info->fix) == 1)		erase &= ~0x400;	logo_height = fb_prepare_logo(info, ops->rotate);	logo_lines = (logo_height + vc->vc_font.height - 1) /		vc->vc_font.height;	q = (unsigned short *) (vc->vc_origin +				vc->vc_size_row * rows);	step = logo_lines * cols;	for (r = q - logo_lines * cols; r < q; r++)		if (scr_readw(r) != vc->vc_video_erase_char)			break;	if (r != q && new_rows >= rows + logo_lines) {		save = kmalloc(logo_lines * new_cols * 2, GFP_KERNEL);		if (save) {			int i = cols < new_cols ? cols : new_cols;			scr_memsetw(save, erase, logo_lines * new_cols * 2);			r = q - step;			for (cnt = 0; cnt < logo_lines; cnt++, r += i)				scr_memcpyw(save + cnt * new_cols, r, 2 * i);			r = q;		}	}	if (r == q) {		/* We can scroll screen down */		r = q - step - cols;		for (cnt = rows - logo_lines; cnt > 0; cnt--) {			scr_memcpyw(r + step, r, vc->vc_size_row);			r -= cols;		}		if (!save) {			vc->vc_y += logo_lines;			vc->vc_pos += logo_lines * vc->vc_size_row;		}	}	scr_memsetw((unsigned short *) vc->vc_origin,		    erase,		    vc->vc_size_row * logo_lines);	if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) {		fbcon_clear_margins(vc, 0);		update_screen(vc);	}	if (save) {		q = (unsigned short *) (vc->vc_origin +					vc->vc_size_row *					rows);		scr_memcpyw(q, save, logo_lines * new_cols * 2);		vc->vc_y += logo_lines;		vc->vc_pos += logo_lines * vc->vc_size_row;		kfree(save);	}	if (logo_lines > vc->vc_bottom) {		logo_shown = FBCON_LOGO_CANSHOW;		printk(KERN_INFO		       "fbcon_init: disable boot-logo (boot-logo bigger than screen).\n");	} else if (logo_shown != FBCON_LOGO_DONTSHOW) {		logo_shown = FBCON_LOGO_DRAW;		vc->vc_top = logo_lines;	}}#ifdef CONFIG_FB_TILEBLITTINGstatic void set_blitting_type(struct vc_data *vc, struct fb_info *info,			      struct display *p){	struct fbcon_ops *ops = info->fbcon_par;	ops->p = (p) ? p : &fb_display[vc->vc_num];	if ((info->flags & FBINFO_MISC_TILEBLITTING))		fbcon_set_tileops(vc, info, p, ops);	else {		fbcon_set_rotation(info, ops->p);		fbcon_set_bitops(ops);	}}#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;	ops->p = (p) ? p : &fb_display[vc->vc_num];	fbcon_set_rotation(info, ops->p);	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) {		fbcon_del_cursor_timer(oldinfo);		kfree(ops->cursor_state.mask);		kfree(ops->cursor_data);		kfree(ops->fontbuffer);		kfree(oldinfo->fbcon_par);		oldinfo->fbcon_par = NULL;		module_put(oldinfo->fbops->owner);		/*		  If oldinfo and newinfo are driving the same hardware,		  the fb_release() method of oldinfo may attempt to		  restore the hardware state.  This will leave the		  newinfo in an undefined state. Thus, a call to		  fb_set_par() may be needed for the newinfo.		*/		if (newinfo->fbops->fb_set_par)			newinfo->fbops->fb_set_par(newinfo);	}	return err;}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 && !(ops->flags & FBCON_FLAGS_INIT))		info->fbops->fb_set_par(info);	ops->flags |= FBCON_FLAGS_INIT;	ops->graphics = 0;	if (vc)		fbcon_set_disp(info, &info->var, vc);	else		fbcon_preset_disp(info, &info->var, 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);	}	update_screen(vc_cons[fg_console].d);}/** *	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) 			fbcon_add_cursor_timer(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->rotate = var->rotate;	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;	var->rotate = disp->rotate;}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;	const 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;	ops->graphics = 1;	ops->cur_rotate = -1;	info->fbcon_par = ops;	p->con_rotate = rotate;	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 = (void *)(p->fontdata = font->data);		vc->vc_font.charcount = 256; /* FIXME  Need to support more fonts */	}	cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);	rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);	cols /= vc->vc_font.width;	rows /= vc->vc_font.height;	vc_resize(vc, 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;		/*

⌨️ 快捷键说明

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