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

📄 vga16fb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        dx = area->dx / 4;        width = area->width / 4;        if (area->dy < area->sy || (area->dy == area->sy && dx < sx)) {                line_ofs = info->fix.line_length - width;                dest = info->screen_base + dx + area->dy * info->fix.line_length;                src = info->screen_base + sx + area->sy * info->fix.line_length;                while (height--) {                        for (x = 0; x < width; x++) {                                readb(src);                                writeb(0, dest);                                src++;                                dest++;                        }                        src += line_ofs;                        dest += line_ofs;                }        } else {                line_ofs = info->fix.line_length - width;                dest = info->screen_base + dx + width +			(area->dy + height - 1) * info->fix.line_length;                src = info->screen_base + sx + width +			(area->sy + height - 1) * info->fix.line_length;                while (height--) {                        for (x = 0; x < width; x++) {                                --src;                                --dest;                                readb(src);                                writeb(0, dest);                        }                        src -= line_ofs;                        dest -= line_ofs;                }        }        setsr(oldsr);        setop(oldop);        setmode(oldmode);        setindex(oldindex);}static void vga16fb_copyarea(struct fb_info *info, const struct fb_copyarea *area){	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy; 	int x, x2, y2, old_dx, old_dy, vxres, vyres;	int height, width, line_ofs;	char __iomem *dst = NULL;	char __iomem *src = NULL;	vxres = info->var.xres_virtual;	vyres = info->var.yres_virtual;	if (area->dx > vxres || area->sx > vxres || area->dy > vyres ||	    area->sy > vyres)		return;	/* clip the destination */	old_dx = area->dx;	old_dy = area->dy;	/*	 * We could use hardware clipping but on many cards you get around	 * hardware clipping by writing to framebuffer directly.	 */	x2 = area->dx + area->width;	y2 = area->dy + area->height;	dx = area->dx > 0 ? area->dx : 0;	dy = area->dy > 0 ? area->dy : 0;	x2 = x2 < vxres ? x2 : vxres;	y2 = y2 < vyres ? y2 : vyres;	width = x2 - dx;	height = y2 - dy;	if (sx + dx < old_dx || sy + dy < old_dy)		return;	/* update sx1,sy1 */	sx += (dx - old_dx);	sy += (dy - old_dy);	/* the source must be completely inside the virtual screen */	if (sx + width > vxres || sy + height > vyres)		return;	switch (info->fix.type) {	case FB_TYPE_VGA_PLANES:		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {			width = width/8;			height = height;			line_ofs = info->fix.line_length - width;			setmode(1);			setop(0);			setsr(0xf);			if (dy < sy || (dy == sy && dx < sx)) {				dst = info->screen_base + (dx/8) + dy * info->fix.line_length;				src = info->screen_base + (sx/8) + sy * info->fix.line_length;				while (height--) {					for (x = 0; x < width; x++) {						readb(src);						writeb(0, dst);						dst++;						src++;					}					src += line_ofs;					dst += line_ofs;				}			} else {				dst = info->screen_base + (dx/8) + width + 					(dy + height - 1) * info->fix.line_length;				src = info->screen_base + (sx/8) + width + 					(sy + height  - 1) * info->fix.line_length;				while (height--) {					for (x = 0; x < width; x++) {						dst--;						src--;						readb(src);						writeb(0, dst);					}					src -= line_ofs;					dst -= line_ofs;				}			}		} else 			vga_8planes_copyarea(info, area);		break;	case FB_TYPE_PACKED_PIXELS:	default:		cfb_copyarea(info, area);		break;	}}#define TRANS_MASK_LOW  {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}#define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \			 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}#if defined(__LITTLE_ENDIAN)static const u16 transl_l[] = TRANS_MASK_LOW;static const u16 transl_h[] = TRANS_MASK_HIGH;#elif defined(__BIG_ENDIAN)static const u16 transl_l[] = TRANS_MASK_HIGH;static const u16 transl_h[] = TRANS_MASK_LOW;#else#error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes"#endifstatic void vga_8planes_imageblit(struct fb_info *info, const struct fb_image *image){        char oldindex = getindex();        char oldmode = setmode(0x40);        char oldop = setop(0);        char oldsr = setsr(0);        char oldmask = selectmask();        const char *cdat = image->data;	u32 dx = image->dx;        char __iomem *where;        int y;        dx /= 4;        where = info->screen_base + dx + image->dy * info->fix.line_length;        setmask(0xff);        writeb(image->bg_color, where);        readb(where);        selectmask();        setmask(image->fg_color ^ image->bg_color);        setmode(0x42);        setop(0x18);        for (y = 0; y < image->height; y++, where += info->fix.line_length)                writew(transl_h[cdat[y]&0xF] | transl_l[cdat[y] >> 4], where);        setmask(oldmask);        setsr(oldsr);        setop(oldop);        setmode(oldmode);        setindex(oldindex);}static void vga_imageblit_expand(struct fb_info *info, const struct fb_image *image){	char __iomem *where = info->screen_base + (image->dx/8) +		image->dy * info->fix.line_length;	struct vga16fb_par *par = info->par;	char *cdat = (char *) image->data;	char __iomem *dst;	int x, y;	switch (info->fix.type) {	case FB_TYPE_VGA_PLANES:		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {			if (par->isVGA) {				setmode(2);				setop(0);				setsr(0xf);				setcolor(image->fg_color);				selectmask();								setmask(0xff);				writeb(image->bg_color, where);				rmb();				readb(where); /* fill latches */				setmode(3);				wmb();				for (y = 0; y < image->height; y++) {					dst = where;					for (x = image->width/8; x--;) 						writeb(*cdat++, dst++);					where += info->fix.line_length;				}				wmb();			} else {				setmode(0);				setop(0);				setsr(0xf);				setcolor(image->bg_color);				selectmask();								setmask(0xff);				for (y = 0; y < image->height; y++) {					dst = where;					for (x=image->width/8; x--;){						rmw(dst);						setcolor(image->fg_color);						selectmask();						if (*cdat) {							setmask(*cdat++);							rmw(dst++);						}					}					where += info->fix.line_length;				}			}		} else 			vga_8planes_imageblit(info, image);		break;	case FB_TYPE_PACKED_PIXELS:	default:		cfb_imageblit(info, image);		break;	}}static void vga_imageblit_color(struct fb_info *info, const struct fb_image *image){	/*	 * Draw logo 	 */	struct vga16fb_par *par = info->par;	char __iomem *where =		info->screen_base + image->dy * info->fix.line_length +		image->dx/8;	const char *cdat = image->data;	char __iomem *dst;	int x, y;	switch (info->fix.type) {	case FB_TYPE_VGA_PLANES:		if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4 &&		    par->isVGA) {			setsr(0xf);			setop(0);			setmode(0);						for (y = 0; y < image->height; y++) {				for (x = 0; x < image->width; x++) {					dst = where + x/8;					setcolor(*cdat);					selectmask();					setmask(1 << (7 - (x % 8)));					fb_readb(dst);					fb_writeb(0, dst);					cdat++;				}				where += info->fix.line_length;			}		}		break;	case FB_TYPE_PACKED_PIXELS:		cfb_imageblit(info, image);		break;	default:		break;	}}				static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image){	if (image->depth == 1)		vga_imageblit_expand(info, image);	else		vga_imageblit_color(info, image);}static struct fb_ops vga16fb_ops = {	.owner		= THIS_MODULE,	.fb_open        = vga16fb_open,	.fb_release     = vga16fb_release,	.fb_check_var	= vga16fb_check_var,	.fb_set_par	= vga16fb_set_par,	.fb_setcolreg 	= vga16fb_setcolreg,	.fb_pan_display = vga16fb_pan_display,	.fb_blank 	= vga16fb_blank,	.fb_fillrect	= vga16fb_fillrect,	.fb_copyarea	= vga16fb_copyarea,	.fb_imageblit	= vga16fb_imageblit,};#ifndef MODULEstatic int vga16fb_setup(char *options){	char *this_opt;		if (!options || !*options)		return 0;		while ((this_opt = strsep(&options, ",")) != NULL) {		if (!*this_opt) continue;	}	return 0;}#endifstatic int __init vga16fb_probe(struct platform_device *dev){	struct fb_info *info;	struct vga16fb_par *par;	int i;	int ret = 0;	printk(KERN_DEBUG "vga16fb: initializing\n");	info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev);	if (!info) {		ret = -ENOMEM;		goto err_fb_alloc;	}	/* XXX share VGA_FB_PHYS and I/O region with vgacon and others */	info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);	if (!info->screen_base) {		printk(KERN_ERR "vga16fb: unable to map device\n");		ret = -ENOMEM;		goto err_ioremap;	}	printk(KERN_INFO "vga16fb: mapped to 0x%p\n", info->screen_base);	par = info->par;	par->isVGA = screen_info.orig_video_isVGA;	par->palette_blanked = 0;	par->vesa_blanked = 0;	i = par->isVGA? 6 : 2;		vga16fb_defined.red.length   = i;	vga16fb_defined.green.length = i;	vga16fb_defined.blue.length  = i;		/* name should not depend on EGA/VGA */	info->fbops = &vga16fb_ops;	info->var = vga16fb_defined;	info->fix = vga16fb_fix;	/* supports rectangles with widths of multiples of 8 */	info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31;	info->flags = FBINFO_FLAG_DEFAULT |		FBINFO_HWACCEL_YPAN;	i = (info->var.bits_per_pixel == 8) ? 256 : 16;	ret = fb_alloc_cmap(&info->cmap, i, 0);	if (ret) {		printk(KERN_ERR "vga16fb: unable to allocate colormap\n");		ret = -ENOMEM;		goto err_alloc_cmap;	}	if (vga16fb_check_var(&info->var, info)) {		printk(KERN_ERR "vga16fb: unable to validate variable\n");		ret = -EINVAL;		goto err_check_var;	}	vga16fb_update_fix(info);	if (register_framebuffer(info) < 0) {		printk(KERN_ERR "vga16fb: unable to register framebuffer\n");		ret = -EINVAL;		goto err_check_var;	}	printk(KERN_INFO "fb%d: %s frame buffer device\n",	       info->node, info->fix.id);	platform_set_drvdata(dev, info);	return 0; err_check_var:	fb_dealloc_cmap(&info->cmap); err_alloc_cmap:	iounmap(info->screen_base); err_ioremap:	framebuffer_release(info); err_fb_alloc:	return ret;}static int vga16fb_remove(struct platform_device *dev){	struct fb_info *info = platform_get_drvdata(dev);	if (info) {		unregister_framebuffer(info);		iounmap(info->screen_base);		fb_dealloc_cmap(&info->cmap);	/* XXX unshare VGA regions */		framebuffer_release(info);	}	return 0;}static struct platform_driver vga16fb_driver = {	.probe = vga16fb_probe,	.remove = vga16fb_remove,	.driver = {		.name = "vga16fb",	},};static struct platform_device *vga16fb_device;static int __init vga16fb_init(void){	int ret;#ifndef MODULE	char *option = NULL;	if (fb_get_options("vga16fb", &option))		return -ENODEV;	vga16fb_setup(option);#endif	ret = platform_driver_register(&vga16fb_driver);	if (!ret) {		vga16fb_device = platform_device_alloc("vga16fb", 0);		if (vga16fb_device)			ret = platform_device_add(vga16fb_device);		else			ret = -ENOMEM;		if (ret) {			platform_device_put(vga16fb_device);			platform_driver_unregister(&vga16fb_driver);		}	}	return ret;}static void __exit vga16fb_exit(void){	platform_device_unregister(vga16fb_device);	platform_driver_unregister(&vga16fb_driver);}MODULE_DESCRIPTION("Legacy VGA framebuffer device driver");MODULE_LICENSE("GPL");module_init(vga16fb_init);module_exit(vga16fb_exit);/* * Overrides for Emacs so that we follow Linus's tabbing style. * --------------------------------------------------------------------------- * Local variables: * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

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