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

📄 sbusfb.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/drivers/video/sbusfb.c -- SBUS or UPA based frame buffer device * *	Copyright (C) 1998 Jakub Jelinek * *  This driver is partly based on the Open Firmware console driver * *	Copyright (C) 1997 Geert Uytterhoeven * *  and SPARC console subsystem * *      Copyright (C) 1995 Peter Zaitcev (zaitcev@lab.ipmce.su) *      Copyright (C) 1995-1997 David S. Miller (davem@caip.rutgers.edu) *      Copyright (C) 1995-1996 Miguel de Icaza (miguel@nuclecu.unam.mx) *      Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) *      Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) *      Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * *  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. */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/malloc.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/fb.h>#include <linux/selection.h>#include <linux/init.h>#include <linux/console.h>#include <linux/kd.h>#include <linux/vt_kern.h>#include <asm/uaccess.h>#include <asm/pgtable.h>	/* io_remap_page_range() */#include <video/sbusfb.h>#define DEFAULT_CURSOR_BLINK_RATE       (2*HZ/5)#define CURSOR_SHAPE			1#define CURSOR_BLINK			2    /*     *  Interface used by the world     */int sbusfb_init(void);int sbusfb_setup(char*);static int currcon;static int defx_margin = -1, defy_margin = -1;static char fontname[40] __initdata = { 0 };static int curblink __initdata = 1;static struct {	int depth;	int xres, yres;	int x_margin, y_margin;} def_margins [] = {	{ 8, 1280, 1024, 64, 80 },	{ 8, 1152, 1024, 64, 80 },	{ 8, 1152, 900,  64, 18 },	{ 8, 1024, 768,  0,  0 },	{ 8, 800, 600, 16, 12 },	{ 8, 640, 480, 0, 0 },	{ 1, 1152, 900,  8,  18 },	{ 0 },};static int sbusfb_open(struct fb_info *info, int user);static int sbusfb_release(struct fb_info *info, int user);static int sbusfb_mmap(struct fb_info *info, struct file *file, 			struct vm_area_struct *vma);static int sbusfb_get_fix(struct fb_fix_screeninfo *fix, int con,			struct fb_info *info);static int sbusfb_get_var(struct fb_var_screeninfo *var, int con,			struct fb_info *info);static int sbusfb_set_var(struct fb_var_screeninfo *var, int con,			struct fb_info *info);static int sbusfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,			struct fb_info *info);static int sbusfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,			struct fb_info *info);static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,			    u_long arg, int con, struct fb_info *info);static void sbusfb_cursor(struct display *p, int mode, int x, int y);static void sbusfb_clear_margin(struct display *p, int s);			        /*     *  Interface to the low level console driver     */static int sbusfbcon_switch(int con, struct fb_info *info);static int sbusfbcon_updatevar(int con, struct fb_info *info);static void sbusfbcon_blank(int blank, struct fb_info *info);    /*     *  Internal routines     */static int sbusfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,			    u_int *transp, struct fb_info *info);static int sbusfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,			    u_int transp, struct fb_info *info);static void do_install_cmap(int con, struct fb_info *info);static struct fb_ops sbusfb_ops = {	owner:		THIS_MODULE,	fb_open:	sbusfb_open,	fb_release:	sbusfb_release,	fb_get_fix:	sbusfb_get_fix,	fb_get_var:	sbusfb_get_var,	fb_set_var:	sbusfb_set_var,	fb_get_cmap:	sbusfb_get_cmap,	fb_set_cmap:	sbusfb_set_cmap,	fb_ioctl:	sbusfb_ioctl,	fb_mmap:	sbusfb_mmap,};    /*     *  Open/Release the frame buffer device     */static int sbusfb_open(struct fb_info *info, int user){	struct fb_info_sbusfb *fb = sbusfbinfo(info);		if (user) {		if (fb->open == 0) {			fb->mmaped = 0;			fb->vtconsole = -1;		}		fb->open++;	} else		fb->consolecnt++;	return 0;}static int sbusfb_release(struct fb_info *info, int user){	struct fb_info_sbusfb *fb = sbusfbinfo(info);	if (user) {			fb->open--;		if (fb->open == 0) {			if (fb->vtconsole != -1) {				vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;				if (fb->mmaped) {					fb->graphmode--;					sbusfb_clear_margin(&fb_display[fb->vtconsole], 0);				}			}			if (fb->reset)				fb->reset(fb);		}	} else		fb->consolecnt--;	return 0;}static unsigned long sbusfb_mmapsize(struct fb_info_sbusfb *fb, long size){	if (size == SBUS_MMAP_EMPTY) return 0;	if (size >= 0) return size;	return fb->type.fb_size * (-size);}static int sbusfb_mmap(struct fb_info *info, struct file *file, 			struct vm_area_struct *vma){	struct fb_info_sbusfb *fb = sbusfbinfo(info);	unsigned int size, page, r, map_size;	unsigned long map_offset = 0;	unsigned long off;	int i;                                        	size = vma->vm_end - vma->vm_start;	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))		return -EINVAL;	off = vma->vm_pgoff << PAGE_SHIFT;	/* To stop the swapper from even considering these pages */	vma->vm_flags |= (VM_SHM| VM_LOCKED);	#ifdef __sparc_v9__	/* Align it as much as desirable */	{		unsigned long j, alignment, s = 0;		int max = -1;				map_offset = (vma->vm_pgoff << PAGE_SHIFT) + size;		for (i = 0; fb->mmap_map[i].size; i++) {			if (fb->mmap_map[i].voff < off)				continue;			if (fb->mmap_map[i].voff >= map_offset)				break;			if (max < 0 || sbusfb_mmapsize(fb,fb->mmap_map[i].size) > s) {				max = i;				s = sbusfb_mmapsize(fb,fb->mmap_map[max].size);			}		}		if (max >= 0) {			j = s;			if (fb->mmap_map[max].voff + j > map_offset)				j = map_offset - fb->mmap_map[max].voff;			for (alignment = 0x400000; alignment > PAGE_SIZE; alignment >>= 3)				if (j >= alignment && !(fb->mmap_map[max].poff & (alignment - 1)))					break;			if (alignment > PAGE_SIZE) {				j = alignment;				alignment = j - ((vma->vm_start + fb->mmap_map[max].voff - off) & (j - 1));				if (alignment != j) {					struct vm_area_struct *vmm = find_vma(current->mm, vma->vm_start);					if (!vmm || vmm->vm_start >= vma->vm_end + alignment) {						vma->vm_start += alignment;						vma->vm_end += alignment;					}				}			}		}	}#endif		/* Each page, see which map applies */	for (page = 0; page < size; ){		map_size = 0;		for (i = 0; fb->mmap_map[i].size; i++)			if (fb->mmap_map[i].voff == off+page) {				map_size = sbusfb_mmapsize(fb,fb->mmap_map[i].size);#ifdef __sparc_v9__#define POFF_MASK	(PAGE_MASK|0x1UL)#else#define POFF_MASK	(PAGE_MASK)#endif								map_offset = (fb->physbase + fb->mmap_map[i].poff) & POFF_MASK;				break;			}		if (!map_size){			page += PAGE_SIZE;			continue;		}		if (page + map_size > size)			map_size = size - page;		r = io_remap_page_range (vma->vm_start+page, map_offset, map_size, vma->vm_page_prot, fb->iospace);		if (r)			return -EAGAIN;		page += map_size;	}		vma->vm_flags |= VM_IO;	if (!fb->mmaped) {		int lastconsole = 0;				if (info->display_fg)			lastconsole = info->display_fg->vc_num;		fb->mmaped = 1;		if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {			fb->vtconsole = lastconsole;			fb->graphmode++;			vt_cons [lastconsole]->vc_mode = KD_GRAPHICS;			vc_cons[lastconsole].d->vc_sw->con_cursor(vc_cons[lastconsole].d,CM_ERASE);		} else if (fb->unblank && !fb->blanked)			(*fb->unblank)(fb);	}	return 0;}static void sbusfb_clear_margin(struct display *p, int s){	struct fb_info_sbusfb *fb = sbusfbinfod(p);	if (fb->switch_from_graph)		(*fb->switch_from_graph)(fb);	if (fb->fill) {		unsigned short rects [16];		rects [0] = 0;		rects [1] = 0;		rects [2] = fb->var.xres_virtual;		rects [3] = fb->y_margin;		rects [4] = 0;		rects [5] = fb->y_margin;		rects [6] = fb->x_margin;		rects [7] = fb->var.yres_virtual;		rects [8] = fb->var.xres_virtual - fb->x_margin;		rects [9] = fb->y_margin;		rects [10] = fb->var.xres_virtual;		rects [11] = fb->var.yres_virtual;		rects [12] = fb->x_margin;		rects [13] = fb->var.yres_virtual - fb->y_margin;		rects [14] = fb->var.xres_virtual - fb->x_margin;		rects [15] = fb->var.yres_virtual;		(*fb->fill)(fb, p, s, 4, rects);	} else {		unsigned char *fb_base = p->screen_base, *q;		int skip_bytes = fb->y_margin * fb->var.xres_virtual;		int scr_size = fb->var.xres_virtual * fb->var.yres_virtual;		int h, he, incr, size;		he = fb->var.yres;		if (fb->var.bits_per_pixel == 1) {			fb_base -= (skip_bytes + fb->x_margin) / 8;			skip_bytes /= 8;			scr_size /= 8;			fb_memset255 (fb_base, skip_bytes - fb->x_margin / 8);			fb_memset255 (fb_base + scr_size - skip_bytes + fb->x_margin / 8, skip_bytes - fb->x_margin / 8);			incr = fb->var.xres_virtual / 8;			size = fb->x_margin / 8 * 2;			for (q = fb_base + skip_bytes - fb->x_margin / 8, h = 0;			     h <= he; q += incr, h++)				fb_memset255 (q, size);		} else {			fb_base -= (skip_bytes + fb->x_margin);			memset (fb_base, attr_bgcol(p,s), skip_bytes - fb->x_margin);			memset (fb_base + scr_size - skip_bytes + fb->x_margin, attr_bgcol(p,s), skip_bytes - fb->x_margin);			incr = fb->var.xres_virtual;			size = fb->x_margin * 2;			for (q = fb_base + skip_bytes - fb->x_margin, h = 0;			     h <= he; q += incr, h++)				memset (q, attr_bgcol(p,s), size);		}	}}static void sbusfb_disp_setup(struct display *p){	struct fb_info_sbusfb *fb = sbusfbinfod(p);	if (fb->setup)		fb->setup(p);		sbusfb_clear_margin(p, 0);}    /*     *  Get the Fixed Part of the Display     */static int sbusfb_get_fix(struct fb_fix_screeninfo *fix, int con,			  struct fb_info *info){	struct fb_info_sbusfb *fb = sbusfbinfo(info);	memcpy(fix, &fb->fix, sizeof(struct fb_fix_screeninfo));	return 0;}    /*     *  Get the User Defined Part of the Display     */static int sbusfb_get_var(struct fb_var_screeninfo *var, int con,			  struct fb_info *info){	struct fb_info_sbusfb *fb = sbusfbinfo(info);	memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));	return 0;}    /*     *  Set the User Defined Part of the Display     */static int sbusfb_set_var(struct fb_var_screeninfo *var, int con,			  struct fb_info *info){       struct display *display;       int activate = var->activate;       if(con >= 0)               display = &fb_display[con];       else               display = info->disp;       /* simple check for equality until fully implemented -E */       if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {               if (display->var.xres != var->xres ||                       display->var.yres != var->yres ||                       display->var.xres_virtual != var->xres_virtual ||                       display->var.yres_virtual != var->yres_virtual ||                       display->var.bits_per_pixel != var->bits_per_pixel ||                       display->var.accel_flags != var->accel_flags) {                       return -EINVAL;               }       }       return 0;}    /*     *  Hardware cursor     */     static int sbus_hw_scursor (struct fbcursor *cursor, struct fb_info_sbusfb *fb){	int op;	int i, bytes = 0;	struct fbcursor f;	char red[2], green[2], blue[2];

⌨️ 快捷键说明

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