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

📄 amifb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	 * Hardware limits for AGA:	 *	 *	parameter  min    max  step	 *	---------  ---   ----  ----	 *	diwstrt_h    0   2047     1	 *	diwstrt_v    0   2047     1	 *	diwstop_h    0   4095     1	 *	diwstop_v    0   4095     1	 *	 *	ddfstrt      0   2032    16	 *	ddfstop      0   2032    16	 *	 *	htotal       8   2048     8	 *	hsstrt       0   2040     8	 *	hsstop       0   2040     8	 *	vtotal       1   4096     1	 *	vsstrt       0   4095     1	 *	vsstop       0   4095     1	 *	hcenter      0   2040     8	 *	 *	hbstrt       0   2047     1	 *	hbstop       0   2047     1	 *	vbstrt       0   4095     1	 *	vbstop       0   4095     1	 *	 * Horizontal values are in 35 ns (SHRES) pixels	 * Vertical values are in half scanlines	 *//* bplcon1 (smooth scrolling) */#define hscroll2hw(hscroll) \	(((hscroll)<<12 & 0x3000) | ((hscroll)<<8 & 0xc300) | \	 ((hscroll)<<4 & 0x0c00) | ((hscroll)<<2 & 0x00f0) | ((hscroll)>>2 & 0x000f))/* diwstrt/diwstop/diwhigh (visible display window) */#define diwstrt2hw(diwstrt_h, diwstrt_v) \	(((diwstrt_v)<<7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))#define diwstop2hw(diwstop_h, diwstop_v) \	(((diwstop_v)<<7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))#define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \	(((diwstop_h)<<3 & 0x2000) | ((diwstop_h)<<11 & 0x1800) | \	 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \	 ((diwstrt_h)<<3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))/* ddfstrt/ddfstop (display DMA) */#define ddfstrt2hw(ddfstrt)	div8(ddfstrt)#define ddfstop2hw(ddfstop)	div8(ddfstop)/* hsstrt/hsstop/htotal/vsstrt/vsstop/vtotal/hcenter (sync timings) */#define hsstrt2hw(hsstrt)	(div8(hsstrt))#define hsstop2hw(hsstop)	(div8(hsstop))#define htotal2hw(htotal)	(div8(htotal)-1)#define vsstrt2hw(vsstrt)	(div2(vsstrt))#define vsstop2hw(vsstop)	(div2(vsstop))#define vtotal2hw(vtotal)	(div2(vtotal)-1)#define hcenter2hw(htotal)	(div8(htotal))/* hbstrt/hbstop/vbstrt/vbstop (blanking timings) */#define hbstrt2hw(hbstrt)	(((hbstrt)<<8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))#define hbstop2hw(hbstop)	(((hbstop)<<8 & 0x0700) | ((hbstop)>>3 & 0x00ff))#define vbstrt2hw(vbstrt)	(div2(vbstrt))#define vbstop2hw(vbstop)	(div2(vbstop))/* colour */#define rgb2hw8_high(red, green, blue) \	(((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))#define rgb2hw8_low(red, green, blue) \	(((red & 0x0f)<<8) | ((green & 0x0f)<<4) | (blue & 0x0f))#define rgb2hw4(red, green, blue) \	(((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))#define rgb2hw2(red, green, blue) \	(((red & 0xc0)<<4) | (green & 0xc0) | ((blue & 0xc0)>>4))/* sprpos/sprctl (sprite positioning) */#define spr2hw_pos(start_v, start_h) \	(((start_v)<<7&0xff00) | ((start_h)>>3&0x00ff))#define spr2hw_ctl(start_v, start_h, stop_v) \	(((stop_v)<<7&0xff00) | ((start_v)>>4&0x0040) | ((stop_v)>>5&0x0020) | \	 ((start_h)<<3&0x0018) | ((start_v)>>7&0x0004) | ((stop_v)>>8&0x0002) | \	 ((start_h)>>2&0x0001))/* get current vertical position of beam */#define get_vbpos()	((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))	/*	 * Copper Initialisation List	 */#define COPINITSIZE (sizeof(copins)*40)enum {	cip_bplcon0};	/*	 * Long Frame/Short Frame Copper List	 * Don't change the order, build_copper()/rebuild_copper() rely on this	 */#define COPLISTSIZE (sizeof(copins)*64)enum {	cop_wait, cop_bplcon0,	cop_spr0ptrh, cop_spr0ptrl,	cop_diwstrt, cop_diwstop,	cop_diwhigh,};	/*	 * Pixel modes for Bitplanes and Sprites	 */static u_short bplpixmode[3] = {	BPC0_SHRES,			/*  35 ns */	BPC0_HIRES,			/*  70 ns */	0				/* 140 ns */};static u_short sprpixmode[3] = {	BPC3_SPRES1 | BPC3_SPRES0,	/*  35 ns */	BPC3_SPRES1,			/*  70 ns */	BPC3_SPRES0			/* 140 ns */};	/*	 * Fetch modes for Bitplanes and Sprites	 */static u_short bplfetchmode[3] = {	0,				/* 1x */	FMODE_BPL32,			/* 2x */	FMODE_BPAGEM | FMODE_BPL32	/* 4x */};static u_short sprfetchmode[3] = {	0,				/* 1x */	FMODE_SPR32,			/* 2x */	FMODE_SPAGEM | FMODE_SPR32	/* 4x */};	/*	 * Interface used by the world	 */int amifb_setup(char*);static int amifb_check_var(struct fb_var_screeninfo *var,			   struct fb_info *info);static int amifb_set_par(struct fb_info *info);static int amifb_setcolreg(unsigned regno, unsigned red, unsigned green,			   unsigned blue, unsigned transp,			   struct fb_info *info);static int amifb_blank(int blank, struct fb_info *info);static int amifb_pan_display(struct fb_var_screeninfo *var,			     struct fb_info *info);static void amifb_fillrect(struct fb_info *info,			   const struct fb_fillrect *rect);static void amifb_copyarea(struct fb_info *info,			   const struct fb_copyarea *region);static void amifb_imageblit(struct fb_info *info,			    const struct fb_image *image);static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);	/*	 * Interface to the low level console driver	 */static void amifb_deinit(void);	/*	 * Internal routines	 */static int flash_cursor(void);static irqreturn_t amifb_interrupt(int irq, void *dev_id);static u_long chipalloc(u_long size);static void chipfree(void);	/*	 * Hardware routines	 */static int ami_decode_var(struct fb_var_screeninfo *var,                          struct amifb_par *par);static int ami_encode_var(struct fb_var_screeninfo *var,                          struct amifb_par *par);static void ami_pan_var(struct fb_var_screeninfo *var);static int ami_update_par(void);static void ami_update_display(void);static void ami_init_display(void);static void ami_do_blank(void);static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix);static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);static int ami_get_cursorstate(struct fb_cursorstate *state);static int ami_set_cursorstate(struct fb_cursorstate *state);static void ami_set_sprite(void);static void ami_init_copper(void);static void ami_reinit_copper(void);static void ami_build_copper(void);static void ami_rebuild_copper(void);static struct fb_ops amifb_ops = {	.owner		= THIS_MODULE,	.fb_check_var	= amifb_check_var,	.fb_set_par	= amifb_set_par,	.fb_setcolreg	= amifb_setcolreg,	.fb_blank	= amifb_blank,	.fb_pan_display	= amifb_pan_display,	.fb_fillrect	= amifb_fillrect,	.fb_copyarea	= amifb_copyarea,	.fb_imageblit	= amifb_imageblit,	.fb_ioctl	= amifb_ioctl,};static void __init amifb_setup_mcap(char *spec){	char *p;	int vmin, vmax, hmin, hmax;	/* Format for monitor capabilities is: <Vmin>;<Vmax>;<Hmin>;<Hmax>	 * <V*> vertical freq. in Hz	 * <H*> horizontal freq. in kHz	 */	if (!(p = strsep(&spec, ";")) || !*p)		return;	vmin = simple_strtoul(p, NULL, 10);	if (vmin <= 0)		return;	if (!(p = strsep(&spec, ";")) || !*p)		return;	vmax = simple_strtoul(p, NULL, 10);	if (vmax <= 0 || vmax <= vmin)		return;	if (!(p = strsep(&spec, ";")) || !*p)		return;	hmin = 1000 * simple_strtoul(p, NULL, 10);	if (hmin <= 0)		return;	if (!(p = strsep(&spec, "")) || !*p)		return;	hmax = 1000 * simple_strtoul(p, NULL, 10);	if (hmax <= 0 || hmax <= hmin)		return;	fb_info.monspecs.vfmin = vmin;	fb_info.monspecs.vfmax = vmax;	fb_info.monspecs.hfmin = hmin;	fb_info.monspecs.hfmax = hmax;}int __init amifb_setup(char *options){	char *this_opt;	if (!options || !*options)		return 0;	while ((this_opt = strsep(&options, ",")) != NULL) {		if (!*this_opt)			continue;		if (!strcmp(this_opt, "inverse")) {			amifb_inverse = 1;			fb_invert_cmaps();		} else if (!strcmp(this_opt, "ilbm"))			amifb_ilbm = 1;		else if (!strncmp(this_opt, "monitorcap:", 11))			amifb_setup_mcap(this_opt+11);		else if (!strncmp(this_opt, "fstart:", 7))			min_fstrt = simple_strtoul(this_opt+7, NULL, 0);		else			mode_option = this_opt;	}	if (min_fstrt < 48)		min_fstrt = 48;	return 0;}static int amifb_check_var(struct fb_var_screeninfo *var,			   struct fb_info *info){	int err;	struct amifb_par par;	/* Validate wanted screen parameters */	if ((err = ami_decode_var(var, &par)))		return err;	/* Encode (possibly rounded) screen parameters */	ami_encode_var(var, &par);	return 0;}static int amifb_set_par(struct fb_info *info){	struct amifb_par *par = (struct amifb_par *)info->par;	do_vmode_pan = 0;	do_vmode_full = 0;	/* Decode wanted screen parameters */	ami_decode_var(&info->var, par);	/* Set new videomode */	ami_build_copper();	/* Set VBlank trigger */	do_vmode_full = 1;	/* Update fix for new screen parameters */	if (par->bpp == 1) {		info->fix.type = FB_TYPE_PACKED_PIXELS;		info->fix.type_aux = 0;	} else if (amifb_ilbm) {		info->fix.type = FB_TYPE_INTERLEAVED_PLANES;		info->fix.type_aux = par->next_line;	} else {		info->fix.type = FB_TYPE_PLANES;		info->fix.type_aux = 0;	}	info->fix.line_length = div8(upx(16<<maxfmode, par->vxres));	if (par->vmode & FB_VMODE_YWRAP) {		info->fix.ywrapstep = 1;		info->fix.xpanstep = 0;		info->fix.ypanstep = 0;		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |		    FBINFO_READS_FAST; /* override SCROLL_REDRAW */	} else {		info->fix.ywrapstep = 0;		if (par->vmode & FB_VMODE_SMOOTH_XPAN)			info->fix.xpanstep = 1;		else			info->fix.xpanstep = 16<<maxfmode;		info->fix.ypanstep = 1;		info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;	}	return 0;}	/*	 * Pan or Wrap the Display	 *	 * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag	 */static int amifb_pan_display(struct fb_var_screeninfo *var,			     struct fb_info *info){	if (var->vmode & FB_VMODE_YWRAP) {		if (var->yoffset < 0 ||		    var->yoffset >= info->var.yres_virtual || var->xoffset)			return -EINVAL;	} else {		/*		 * TODO: There will be problems when xpan!=1, so some columns		 * on the right side will never be seen		 */		if (var->xoffset+info->var.xres > upx(16<<maxfmode, info->var.xres_virtual) ||		    var->yoffset+info->var.yres > info->var.yres_virtual)			return -EINVAL;	}	ami_pan_var(var);	info->var.xoffset = var->xoffset;	info->var.yoffset = var->yoffset;	if (var->vmode & FB_VMODE_YWRAP)		info->var.vmode |= FB_VMODE_YWRAP;	else		info->var.vmode &= ~FB_VMODE_YWRAP;	return 0;}#if BITS_PER_LONG == 32#define BYTES_PER_LONG	4#define SHIFT_PER_LONG	5#elif BITS_PER_LONG == 64#define BYTES_PER_LONG	8#define SHIFT_PER_LONG	6#else#define Please update me#endif    /*     *  Compose two values, using a bitmask as decision value     *  This is equivalent to (a & mask) | (b & ~mask)     */static inline unsigned long comp(unsigned long a, unsigned long b,				 unsigned long mask){	return ((a ^ b) & mask) ^ b;}static inline unsigned long xor(unsigned long a, unsigned long b,				unsigned long mask){	return (a & mask) ^ b;}    /*     *  Unaligned forward bit copy using 32-bit or 64-bit memory accesses     */static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,		   int src_idx, u32 n){	unsigned long first, last;	int shift = dst_idx-src_idx, left, right;	unsigned long d0, d1;	int m;	if (!n)		return;	shift = dst_idx-src_idx;	first = ~0UL >> dst_idx;	last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));	if (!shift) {		// Same alignment for source and dest		if (dst_idx+n <= BITS_PER_LONG) {			// Single word			if (last)				first &= last;			*dst = comp(*src, *dst, first);		} else {			// Multiple destination words			// Leading bits			if (first) {				*dst = comp(*src, *dst, first);				dst++;				src++;				n -= BITS_PER_LONG-dst_idx;			}			// Main chunk			n /= BITS_PER_LONG;			while (n >= 8) {				*dst++ = *src++;				*dst++ = *src++;				*dst++ = *src++;				*dst++ = *src++;				*dst++ = *src++;				*dst++ = *src++;				*dst++ = *src++;				*dst++ = *src++;				n -= 8;			}			while (n--)				*dst++ = *src++;			// Trailing bits			if (last)				*dst = comp(*src, *dst, last);		}	} else {		// Different alignment for source and dest		right = shift & (BITS_PER_LONG-1);		left = -shift & (BITS_PER_LONG-1);

⌨️ 快捷键说明

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