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

📄 fbcon.c

📁 Linux程序设计权威指南代码.包含所有章节代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  linux/drivers/video/fbcon.c -- Low level frame buffer based console driver * *	Copyright (C) 1995 Geert Uytterhoeven * * *  This file is based on the original Amiga console driver (amicon.c): * *	Copyright (C) 1993 Hamish Macdonald *			   Greg Harp *	Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk] * *	      with work by William Rucklidge (wjr@cs.cornell.edu) *			   Geert Uytterhoeven *			   Jes Sorensen (jds@kom.auc.dk) *			   Martin Apel * *  and on the original Atari console driver (atacon.c): * *	Copyright (C) 1993 Bjoern Brauel *			   Roman Hodek * *	      with work by Guenther Kelleter *			   Martin Schaller *			   Andreas Schwab * *  Hardware cursor support added by Emmanuel Marty (core@ggi-project.org) *  Smart redraw scrolling, arbitrary font width support, 512char font support *  and software scrollback added by  *                         Jakub Jelinek (jj@ultra.linux.cz) * *  Random hacking by Martin Mares <mj@ucw.cz> * * *  The low level operations for the various display memory organizations are *  now in separate source files. * *  Currently the following organizations are supported: * *    o afb			Amiga bitplanes *    o cfb{2,4,8,16,24,32}	Packed pixels *    o ilbm			Amiga interleaved bitplanes *    o iplan2p[248]		Atari interleaved bitplanes *    o mfb			Monochrome *    o vga			VGA characters/attributes * *  To do: * *    - Implement 16 plane mode (iplan2p16) * * *  This file is subject to the terms and conditions of the GNU General Public *  License.  See the file COPYING in the main directory of this archive for *  more details. */#undef FBCONDEBUG#define CONFIG_MY_LOGO#define CONFIG_MINI_LOGO#if defined(CONFIG_MINI_LOGO) && !defined(CONFIG_MY_LOGO)#error "CONFIG_MINI_LOGO must be used with CONFIG_MY_LOGO"#endif#include <linux/config.h>#include <linux/module.h>#include <linux/types.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/delay.h>	/* MSch: for IRQ probe */#include <linux/tty.h>#include <linux/console.h>#include <linux/string.h>#include <linux/kd.h>#include <linux/malloc.h>#include <linux/fb.h>#include <linux/vt_kern.h>#include <linux/selection.h>#include <linux/smp.h>#include <linux/init.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/uaccess.h>#ifdef CONFIG_AMIGA#include <asm/amigahw.h>#include <asm/amigaints.h>#endif /* CONFIG_AMIGA */#ifdef CONFIG_ATARI#include <asm/atariints.h>#endif#ifdef CONFIG_MAC#include <asm/macints.h>#endif#if defined(__mc68000__) || defined(CONFIG_APUS)#include <asm/machdep.h>#include <asm/setup.h>#endif#ifdef CONFIG_FBCON_VGA_PLANES#include <asm/io.h>#endif#define INCLUDE_LINUX_LOGO_DATA#include <asm/linux_logo.h>/* HACKED by zerow_jp*/#ifdef CONFIG_MINI_LOGO/* mini logo (for SMP)*//* define	MINI_LOGO_H, MINI_LOGO_W, 	MINI_LOGO_X, MINI_LOGO_Y, MINI_LOGO_ADD	unsigned char mini_logo[MINI_LOGO_H*MINI_LOGO_W] */#include <linux/linux_logo_mini.h>#endif#include <video/fbcon.h>#include <video/fbcon-mac.h>	/* for 6x11 font on mac */#include <video/font.h>#ifdef FBCONDEBUG#  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)#else#  define DPRINTK(fmt, args...)#endif#define LOGO_H			80#define LOGO_W			80#define LOGO_LINE	(LOGO_W/8)#ifdef CONFIG_MY_LOGO#define MY_LOGO_LINE   (MY_LOGO_W/8)#endifstruct display fb_display[MAX_NR_CONSOLES];static int logo_lines;static int logo_shown = -1;/* Software scrollback */extern int fbcon_softback_size;static unsigned long softback_buf, softback_curr;static unsigned long softback_in;static unsigned long softback_top, softback_end;static int softback_lines;#define REFCOUNT(fd)	(((int *)(fd))[-1])#define FNTSIZE(fd)	(((int *)(fd))[-2])#define FNTCHARCNT(fd)	(((int *)(fd))[-3])#define FNTSUM(fd)	(((int *)(fd))[-4])#define FONT_EXTRA_WORDS 4#define CM_SOFTBACK	(8)#define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * conp->vc_size_row)static void fbcon_free_font(struct display *);static int fbcon_set_origin(struct vc_data *);/* * Emmanuel: fbcon will now use a hardware cursor if the * low-level driver provides a non-NULL dispsw->cursor pointer, * in which case the hardware should do blinking, etc. * * if dispsw->cursor is NULL, use Atari alike software cursor */static int cursor_drawn = 0;#define CURSOR_DRAW_DELAY		(1)/* # VBL ints between cursor state changes */#define ARM_CURSOR_BLINK_RATE		(10)#define AMIGA_CURSOR_BLINK_RATE		(20)#define ATARI_CURSOR_BLINK_RATE		(42)#define MAC_CURSOR_BLINK_RATE		(32)#define DEFAULT_CURSOR_BLINK_RATE	(20)static int vbl_cursor_cnt = 0;static int cursor_on = 0;static int cursor_blink_rate;static inline void cursor_undrawn(void){    vbl_cursor_cnt = 0;    cursor_drawn = 0;}#define divides(a, b)	((!(a) || (b)%(a)) ? 0 : 1)/* *  Interface used by the world */static const char *fbcon_startup(void);static void fbcon_init(struct vc_data *conp, int init);static void fbcon_deinit(struct vc_data *conp);static int fbcon_changevar(int con);static void fbcon_clear(struct vc_data *conp, int sy, int sx, int height,		       int width);static void fbcon_putc(struct vc_data *conp, int c, int ypos, int xpos);static void fbcon_putcs(struct vc_data *conp, const unsigned short *s, int count,			int ypos, int xpos);static void fbcon_cursor(struct vc_data *conp, int mode);static int fbcon_scroll(struct vc_data *conp, int t, int b, int dir,			 int count);static void fbcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,			int height, int width);static int fbcon_switch(struct vc_data *conp);static int fbcon_blank(struct vc_data *conp, int blank);static int fbcon_font_op(struct vc_data *conp, struct console_font_op *op);static int fbcon_set_palette(struct vc_data *conp, unsigned char *table);static int fbcon_scrolldelta(struct vc_data *conp, int lines);/* *  Internal routines */static void fbcon_setup(int con, int init, int logo);static __inline__ int real_y(struct display *p, int ypos);static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp);static __inline__ void updatescrollmode(struct display *p);static __inline__ void ywrap_up(int unit, struct vc_data *conp,				struct display *p, int count);static __inline__ void ywrap_down(int unit, struct vc_data *conp,				  struct display *p, int count);static __inline__ void ypan_up(int unit, struct vc_data *conp,			       struct display *p, int count);static __inline__ void ypan_down(int unit, struct vc_data *conp,				 struct display *p, int count);static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, int dx,			    int height, int width, u_int y_break);static int fbcon_show_logo(void);#ifdef CONFIG_MAC/* * On the Macintoy, there may or may not be a working VBL int. We need to probe */static int vbl_detected = 0;static void fbcon_vbl_detect(int irq, void *dummy, struct pt_regs *fp){      vbl_detected++;}#endifstatic void cursor_timer_handler(unsigned long dev_addr);static struct timer_list cursor_timer = {    NULL, NULL, 0, 0L, cursor_timer_handler};static void cursor_timer_handler(unsigned long dev_addr){      fbcon_vbl_handler(0, NULL, NULL);      cursor_timer.expires = jiffies+HZ/50;      cursor_timer.data = 0;      cursor_timer.next = cursor_timer.next = NULL;      add_timer(&cursor_timer);}/* *  Low Level Operations */struct display_switch fbcon_dummy;/* NOTE: fbcon cannot be __initfunc: it may be called from take_over_console later */static const char *fbcon_startup(void){    const char *display_desc = "frame buffer device";    int irqres = 1;    static int done = 0;    /*     *  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 || done)	return display_desc;    done = 1;#ifdef CONFIG_AMIGA    if (MACH_IS_AMIGA) {	cursor_blink_rate = AMIGA_CURSOR_BLINK_RATE;	irqres = request_irq(IRQ_AMIGA_VERTB, fbcon_vbl_handler, 0,			     "console/cursor", fbcon_vbl_handler);    }#endif /* CONFIG_AMIGA */#ifdef CONFIG_ATARI    if (MACH_IS_ATARI) {	cursor_blink_rate = ATARI_CURSOR_BLINK_RATE;	irqres = request_irq(IRQ_AUTO_4, fbcon_vbl_handler, IRQ_TYPE_PRIO,			     "console/cursor", fbcon_vbl_handler);    }#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, fbcon_vbl_detect, 0,			     "console/cursor", fbcon_vbl_detect);	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, fbcon_vbl_detect);	if (vbl_detected) {	    /*	     * interrupt based cursor ok	     */	    cursor_blink_rate = MAC_CURSOR_BLINK_RATE;	    irqres = request_irq(IRQ_MAC_VBL, fbcon_vbl_handler, 0,				 "console/cursor", fbcon_vbl_handler);	} 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, fbcon_vbl_handler, SA_SHIRQ,			 "console/cursor", fbcon_vbl_handler);#endif    if (irqres) {	cursor_blink_rate = DEFAULT_CURSOR_BLINK_RATE;	cursor_timer.expires = jiffies+HZ/50;	cursor_timer.data = 0;	cursor_timer.next = cursor_timer.prev = NULL;	add_timer(&cursor_timer);    }    return display_desc;}static void fbcon_init(struct vc_data *conp, int init){    int unit = conp->vc_num;    struct fb_info *info;    /* on which frame buffer will we open this console? */    info = registered_fb[(int)con2fb_map[unit]];    info->changevar = &fbcon_changevar;    fb_display[unit] = *(info->disp);	/* copy from default */    DPRINTK("mode:   %s\n",info->modename);    DPRINTK("visual: %d\n",fb_display[unit].visual);    DPRINTK("res:    %dx%d-%d\n",fb_display[unit].var.xres,	                     fb_display[unit].var.yres,	                     fb_display[unit].var.bits_per_pixel);    fb_display[unit].conp = conp;    fb_display[unit].fb_info = info;    /* clear out the cmap so we don't have dangling pointers */    fb_display[unit].cmap.len = 0;    fb_display[unit].cmap.red = 0;    fb_display[unit].cmap.green = 0;    fb_display[unit].cmap.blue = 0;    fb_display[unit].cmap.transp = 0;    fbcon_setup(unit, init, !init);    /* Must be done after fbcon_setup to prevent excess updates */    conp->vc_display_fg = &info->display_fg;    if (!info->display_fg)        info->display_fg = conp;}static void fbcon_deinit(struct vc_data *conp){    int unit = conp->vc_num;    struct display *p = &fb_display[unit];    fbcon_free_font(p);    p->dispsw = &fbcon_dummy;    p->conp = 0;}static int fbcon_changevar(int con){    if (fb_display[con].conp)	    fbcon_setup(con, 0, 0);    return 0;}static __inline__ void updatescrollmode(struct display *p){    int m;    if (p->scrollmode & __SCROLL_YFIXED)    	return;    if (divides(p->ywrapstep, fontheight(p)) &&	divides(fontheight(p), p->var.yres_virtual))	m = __SCROLL_YWRAP;    else if (divides(p->ypanstep, fontheight(p)) &&	     p->var.yres_virtual >= p->var.yres+fontheight(p))	m = __SCROLL_YPAN;    else if (p->scrollmode & __SCROLL_YNOMOVE)    	m = __SCROLL_YREDRAW;    else	m = __SCROLL_YMOVE;    p->scrollmode = (p->scrollmode & ~__SCROLL_YMASK) | m;}static void fbcon_font_widths(struct display *p){    int i;        p->_fontwidthlog = 0;    for (i = 2; i <= 6; i++)    	if (fontwidth(p) == (1 << i))	    p->_fontwidthlog = i;    p->_fontheightlog = 0;    for (i = 2; i <= 6; i++)    	if (fontheight(p) == (1 << i))	    p->_fontheightlog = i;}#define fontwidthvalid(p,w) ((p)->dispsw->fontwidthmask & FONTWIDTH(w))static void fbcon_setup(int con, int init, int logo){    struct display *p = &fb_display[con];    struct vc_data *conp = p->conp;    int nr_rows, nr_cols;    int old_rows, old_cols;    unsigned short *save = NULL, *r, *q;    int i, charcnt = 256;    struct fbcon_font_desc *font;        if (con != fg_console || (p->fb_info->flags & FBINFO_FLAG_MODULE) ||        p->type == FB_TYPE_TEXT)    	logo = 0;    p->var.xoffset = p->var.yoffset = p->yscroll = 0;  /* reset wrap/pan */    if (con == fg_console && p->type != FB_TYPE_TEXT) {   	if (fbcon_softback_size) {	    if (!softback_buf) {		softback_buf = (unsigned long)kmalloc(fbcon_softback_size, GFP_KERNEL);

⌨️ 快捷键说明

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