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

📄 amifb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	while (1) {		dst += dst_idx >> SHIFT_PER_LONG;		dst_idx &= (BITS_PER_LONG-1);		bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);		if (!--bpp)			break;		color >>= 1;		dst_idx += next_plane*8;	}}static inline void xor_one_line(int bpp, unsigned long next_plane,				unsigned long *dst, int dst_idx, u32 n,				u32 color){	while (color) {		dst += dst_idx >> SHIFT_PER_LONG;		dst_idx &= (BITS_PER_LONG-1);		bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);		if (!--bpp)			break;		color >>= 1;		dst_idx += next_plane*8;	}}static void amifb_fillrect(struct fb_info *info,			   const struct fb_fillrect *rect){	struct amifb_par *par = (struct amifb_par *)info->par;	int dst_idx, x2, y2;	unsigned long *dst;	u32 width, height;	if (!rect->width || !rect->height)		return;	/*	 * We could use hardware clipping but on many cards you get around	 * hardware clipping by writing to framebuffer directly.	 * */	x2 = rect->dx + rect->width;	y2 = rect->dy + rect->height;	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;	width = x2 - rect->dx;	height = y2 - rect->dy;	dst = (unsigned long *)		((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));	dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;	dst_idx += rect->dy*par->next_line*8+rect->dx;	while (height--) {		switch (rect->rop) {		    case ROP_COPY:			fill_one_line(info->var.bits_per_pixel,				      par->next_plane, dst, dst_idx, width,				      rect->color);			break;		    case ROP_XOR:			xor_one_line(info->var.bits_per_pixel, par->next_plane,				     dst, dst_idx, width, rect->color);			break;		}		dst_idx += par->next_line*8;	}}static inline void copy_one_line(int bpp, unsigned long next_plane,				 unsigned long *dst, int dst_idx,				 unsigned long *src, int src_idx, u32 n){	while (1) {		dst += dst_idx >> SHIFT_PER_LONG;		dst_idx &= (BITS_PER_LONG-1);		src += src_idx >> SHIFT_PER_LONG;		src_idx &= (BITS_PER_LONG-1);		bitcpy(dst, dst_idx, src, src_idx, n);		if (!--bpp)			break;		dst_idx += next_plane*8;		src_idx += next_plane*8;	}}static inline void copy_one_line_rev(int bpp, unsigned long next_plane,				     unsigned long *dst, int dst_idx,				     unsigned long *src, int src_idx, u32 n){	while (1) {		dst += dst_idx >> SHIFT_PER_LONG;		dst_idx &= (BITS_PER_LONG-1);		src += src_idx >> SHIFT_PER_LONG;		src_idx &= (BITS_PER_LONG-1);		bitcpy_rev(dst, dst_idx, src, src_idx, n);		if (!--bpp)			break;		dst_idx += next_plane*8;		src_idx += next_plane*8;	}}static void amifb_copyarea(struct fb_info *info,			   const struct fb_copyarea *area){	struct amifb_par *par = (struct amifb_par *)info->par;	int x2, y2;	u32 dx, dy, sx, sy, width, height;	unsigned long *dst, *src;	int dst_idx, src_idx;	int rev_copy = 0;	/* clip the destination */	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 < info->var.xres_virtual ? x2 : info->var.xres_virtual;	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;	width = x2 - dx;	height = y2 - dy;	if (area->sx + dx < area->dx || area->sy + dy < area->dy)		return;	/* update sx,sy */	sx = area->sx + (dx - area->dx);	sy = area->sy + (dy - area->dy);	/* the source must be completely inside the virtual screen */	if (sx + width > info->var.xres_virtual ||			sy + height > info->var.yres_virtual)		return;	if (dy > sy || (dy == sy && dx > sx)) {		dy += height;		sy += height;		rev_copy = 1;	}	dst = (unsigned long *)		((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));	src = dst;	dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;	src_idx = dst_idx;	dst_idx += dy*par->next_line*8+dx;	src_idx += sy*par->next_line*8+sx;	if (rev_copy) {		while (height--) {			dst_idx -= par->next_line*8;			src_idx -= par->next_line*8;			copy_one_line_rev(info->var.bits_per_pixel,					  par->next_plane, dst, dst_idx, src,					  src_idx, width);		}	} else {		while (height--) {			copy_one_line(info->var.bits_per_pixel,				      par->next_plane, dst, dst_idx, src,				      src_idx, width);			dst_idx += par->next_line*8;			src_idx += par->next_line*8;		}	}}static inline void expand_one_line(int bpp, unsigned long next_plane,				   unsigned long *dst, int dst_idx, u32 n,				   const u8 *data, u32 bgcolor, u32 fgcolor){    const unsigned long *src;    int src_idx;    while (1) {	dst += dst_idx >> SHIFT_PER_LONG;	dst_idx &= (BITS_PER_LONG-1);	if ((bgcolor ^ fgcolor) & 1) {	    src = (unsigned long *)((unsigned long)data & ~(BYTES_PER_LONG-1));	    src_idx = ((unsigned long)data & (BYTES_PER_LONG-1))*8;	    if (fgcolor & 1)		bitcpy(dst, dst_idx, src, src_idx, n);	    else		bitcpy_not(dst, dst_idx, src, src_idx, n);	    /* set or clear */	} else	    bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);	if (!--bpp)	    break;	bgcolor >>= 1;	fgcolor >>= 1;	dst_idx += next_plane*8;    }}static void amifb_imageblit(struct fb_info *info, const struct fb_image *image){	struct amifb_par *par = (struct amifb_par *)info->par;	int x2, y2;	unsigned long *dst;	int dst_idx;	const char *src;	u32 dx, dy, width, height, pitch;	/*	 * We could use hardware clipping but on many cards you get around	 * hardware clipping by writing to framebuffer directly like we are	 * doing here.	 */	x2 = image->dx + image->width;	y2 = image->dy + image->height;	dx = image->dx;	dy = image->dy;	x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;	y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;	width  = x2 - dx;	height = y2 - dy;	if (image->depth == 1) {		dst = (unsigned long *)			((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));		dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;		dst_idx += dy*par->next_line*8+dx;		src = image->data;		pitch = (image->width+7)/8;		while (height--) {			expand_one_line(info->var.bits_per_pixel,					par->next_plane, dst, dst_idx, width,					src, image->bg_color,					image->fg_color);			dst_idx += par->next_line*8;			src += pitch;		}	} else {		c2p_planar(info->screen_base, image->data, dx, dy, width,			   height, par->next_line, par->next_plane,			   image->width, info->var.bits_per_pixel);	}}	/*	 * Amiga Frame Buffer Specific ioctls	 */static int amifb_ioctl(struct fb_info *info,		       unsigned int cmd, unsigned long arg){	union {		struct fb_fix_cursorinfo fix;		struct fb_var_cursorinfo var;		struct fb_cursorstate state;	} crsr;	void __user *argp = (void __user *)arg;	int i;	switch (cmd) {		case FBIOGET_FCURSORINFO:			i = ami_get_fix_cursorinfo(&crsr.fix);			if (i)				return i;			return copy_to_user(argp, &crsr.fix,					    sizeof(crsr.fix)) ? -EFAULT : 0;		case FBIOGET_VCURSORINFO:			i = ami_get_var_cursorinfo(&crsr.var,				((struct fb_var_cursorinfo __user *)arg)->data);			if (i)				return i;			return copy_to_user(argp, &crsr.var,					    sizeof(crsr.var)) ? -EFAULT : 0;		case FBIOPUT_VCURSORINFO:			if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))				return -EFAULT;			return ami_set_var_cursorinfo(&crsr.var,				((struct fb_var_cursorinfo __user *)arg)->data);		case FBIOGET_CURSORSTATE:			i = ami_get_cursorstate(&crsr.state);			if (i)				return i;			return copy_to_user(argp, &crsr.state,					    sizeof(crsr.state)) ? -EFAULT : 0;		case FBIOPUT_CURSORSTATE:			if (copy_from_user(&crsr.state, argp,					   sizeof(crsr.state)))				return -EFAULT;			return ami_set_cursorstate(&crsr.state);	}	return -EINVAL;}	/*	 * Allocate, Clear and Align a Block of Chip Memory	 */static u_long unaligned_chipptr = 0;static inline u_long __init chipalloc(u_long size){	size += PAGE_SIZE-1;	if (!(unaligned_chipptr = (u_long)amiga_chip_alloc(size,							   "amifb [RAM]")))		panic("No Chip RAM for frame buffer");	memset((void *)unaligned_chipptr, 0, size);	return PAGE_ALIGN(unaligned_chipptr);}static inline void chipfree(void){	if (unaligned_chipptr)		amiga_chip_free((void *)unaligned_chipptr);}	/*	 * Initialisation	 */static int __init amifb_init(void){	int tag, i, err = 0;	u_long chipptr;	u_int defmode;#ifndef MODULE	char *option = NULL;	if (fb_get_options("amifb", &option)) {		amifb_video_off();		return -ENODEV;	}	amifb_setup(option);#endif	if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))		return -ENODEV;	/*	 * We request all registers starting from bplpt[0]	 */	if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120,				"amifb [Denise/Lisa]"))		return -EBUSY;	custom.dmacon = DMAF_ALL | DMAF_MASTER;	switch (amiga_chipset) {#ifdef CONFIG_FB_AMIGA_OCS		case CS_OCS:			strcat(fb_info.fix.id, "OCS");default_chipset:			chipset = TAG_OCS;			maxdepth[TAG_SHRES] = 0;	/* OCS means no SHRES */			maxdepth[TAG_HIRES] = 4;			maxdepth[TAG_LORES] = 6;			maxfmode = TAG_FMODE_1;			defmode = amiga_vblank == 50 ? DEFMODE_PAL						     : DEFMODE_NTSC;			fb_info.fix.smem_len = VIDEOMEMSIZE_OCS;			break;#endif /* CONFIG_FB_AMIGA_OCS */#ifdef CONFIG_FB_AMIGA_ECS		case CS_ECS:			strcat(fb_info.fix.id, "ECS");			chipset = TAG_ECS;			maxdepth[TAG_SHRES] = 2;			maxdepth[TAG_HIRES] = 4;			maxdepth[TAG_LORES] = 6;			maxfmode = TAG_FMODE_1;			if (AMIGAHW_PRESENT(AMBER_FF))			    defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL							 : DEFMODE_AMBER_NTSC;			else			    defmode = amiga_vblank == 50 ? DEFMODE_PAL							 : DEFMODE_NTSC;			if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >			    VIDEOMEMSIZE_ECS_1M)				fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M;			else				fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M;			break;#endif /* CONFIG_FB_AMIGA_ECS */#ifdef CONFIG_FB_AMIGA_AGA		case CS_AGA:			strcat(fb_info.fix.id, "AGA");			chipset = TAG_AGA;			maxdepth[TAG_SHRES] = 8;			maxdepth[TAG_HIRES] = 8;			maxdepth[TAG_LORES] = 8;			maxfmode = TAG_FMODE_4;			defmode = DEFMODE_AGA;			if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >			    VIDEOMEMSIZE_AGA_1M)				fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M;			else				fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M;			break;#endif /* CONFIG_FB_AMIGA_AGA */		default:#ifdef CONFIG_FB_AMIGA_OCS			printk("Unknown graphics chipset, defaulting to OCS\n");			strcat(fb_info.fix.id, "Unknown");			goto default_chipset;#else /* CONFIG_FB_AMIGA_OCS */			err = -ENODEV;			goto amifb_error;#endif /* CONFIG_FB_AMIGA_OCS */			break;	}	/*	 * Calculate the Pixel Clock Values for this Machine	 */	{	u_long tmp = DIVUL(200000000000ULL, amiga_eclock);	pixclock[TAG_SHRES] = (tmp + 4) / 8;	/* SHRES:  35 ns / 28 MHz */	pixclock[TAG_HIRES] = (tmp + 2) / 4;	/* HIRES:  70 ns / 14 MHz */	pixclock[TAG_LORES] = (tmp + 1) / 2;	/* LORES: 140 ns /  7 MHz */	}	/*	 * Replace the Tag Values with the Real Pixel Clock Values	 */	for (i = 0; i < NUM_TOTAL_MODES; i++) {		struct fb_videomode *mode = &ami_modedb[i];		tag = mode->pixclock;		if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {			mode->pixclock = pixclock[tag];		}	}	/*	 *  These monitor specs are for a typical Amiga monitor (e.g. A1960)	 */	if (fb_info.monspecs.hfmin == 0) {	    fb_info.monspecs.hfmin = 15000;	    fb_info.monspecs.hfmax = 38000;	    fb_info.monspecs.vfmin = 49;	    fb_info.monspecs.vfmax = 90;	}	fb_info.fbops = &amifb_ops;	fb_info.par = &currentpar;	fb_info.flags = FBINFO_DEFAULT;	if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,			  NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {		err = -EINVAL;		goto amifb_error;	}	fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,				 &fb_info.modelist);	round_down_bpp = 0;	chipptr = chipalloc(fb_info.fix.smem_len+	                    SPRITEMEMSIZE+	                    DUMMYSPRITEMEMSIZE+	                    COPINITSIZE+	                    4*COPLISTSIZE);	assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len);	assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);	assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);	assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);	assignchunk(cop

⌨️ 快捷键说明

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