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

📄 matroxfb_crtc2.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		DAC1064_global_init(PMINFO2);		DAC1064_global_restore(PMINFO2);		down_read(&ACCESS_FBINFO(altout).lock);		for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {			if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2 &&			    ACCESS_FBINFO(outputs[out]).output->program) {				ACCESS_FBINFO(outputs[out]).output->program(ACCESS_FBINFO(outputs[out]).data);			}		}		for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {			if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2 &&			    ACCESS_FBINFO(outputs[out]).output->start) {				ACCESS_FBINFO(outputs[out]).output->start(ACCESS_FBINFO(outputs[out]).data);			}		}		up_read(&ACCESS_FBINFO(altout).lock);		matroxfb_dh_cfbX_init(m2info, p);		my_install_cmap(m2info);	}	return 0;#undef m2info}static int matroxfb_dh_get_cmap(struct fb_cmap* cmap, int kspc, int con,		struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	struct display* dsp;	if (con < 0)		dsp = m2info->fbcon.disp;	else		dsp = fb_display + con;	if (con == m2info->currcon)		return fb_get_cmap(cmap, kspc, matroxfb_dh_getcolreg, info);	else if (dsp->cmap.len)		fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2);	else		fb_copy_cmap(fb_default_cmap(16), cmap, kspc ? 0 : 2);	return 0;#undef m2info}static int matroxfb_dh_set_cmap(struct fb_cmap* cmap, int kspc, int con,		struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	struct display* dsp;	if (con < 0)		dsp = m2info->fbcon.disp;	else		dsp = fb_display + con;	if (dsp->cmap.len != 16) {		int err;		err = fb_alloc_cmap(&dsp->cmap, 16, 0);		if (err)			return err;	}	if (con == m2info->currcon)		return fb_set_cmap(cmap, kspc, matroxfb_dh_setcolreg, info);	else		fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1);	return 0;#undef m2info}static int matroxfb_dh_pan_display(struct fb_var_screeninfo* var, int con,		struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	struct display* dsp;	if (con < 0)		dsp = m2info->fbcon.disp;	else		dsp = fb_display + con;	if (var->xoffset + dsp->var.xres > dsp->var.xres_virtual ||	    var->yoffset + dsp->var.yres > dsp->var.yres_virtual)		return -EINVAL;	if (con == m2info->currcon)		matroxfb_dh_pan_var(m2info, var);	dsp->var.xoffset = var->xoffset;	dsp->var.yoffset = var->yoffset;	return 0;#undef m2info}static int matroxfb_dh_switch(int con, struct fb_info* info);static int matroxfb_dh_get_vblank(const struct matroxfb_dh_fb_info* m2info, struct fb_vblank* vblank) {	MINFO_FROM(m2info->primary_dev);	matroxfb_enable_irq(PMINFO 0);	memset(vblank, 0, sizeof(*vblank));	vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VBLANK;	/* mask out reserved bits + field number (odd/even) */	vblank->vcount = mga_inl(0x3C48) & 0x000007FF;	/* compatibility stuff */	if (vblank->vcount >= m2info->currcon_display->var.yres)		vblank->flags |= FB_VBLANK_VBLANKING;	if (test_bit(0, &ACCESS_FBINFO(irq_flags))) {		vblank->flags |= FB_VBLANK_HAVE_COUNT;		/* Only one writer, aligned int value...		   it should work without lock and without atomic_t */		vblank->count = ACCESS_FBINFO(crtc2).vsync.cnt;	}	return 0;}static int matroxfb_dh_ioctl(struct inode* inode,		struct file* file,		unsigned int cmd,		unsigned long arg,		int con,		struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	MINFO_FROM(m2info->primary_dev);	DBG("matroxfb_crtc2_ioctl")	switch (cmd) {		case FBIOGET_VBLANK:			{				struct fb_vblank vblank;				int err;				err = matroxfb_dh_get_vblank(m2info, &vblank);				if (err)					return err;				if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank)))					return -EFAULT;				return 0;			}		case FBIO_WAITFORVSYNC:			{				u_int32_t crt;				if (get_user(crt, (u_int32_t *)arg))					return -EFAULT;				if (crt != 0)					return -ENODEV;				return matroxfb_wait_for_sync(PMINFO 1);			}		case MATROXFB_SET_OUTPUT_MODE:		case MATROXFB_GET_OUTPUT_MODE:		case MATROXFB_GET_ALL_OUTPUTS:			{				return ACCESS_FBINFO(fbcon.fbops)->fb_ioctl(inode, file, cmd, arg, con, &ACCESS_FBINFO(fbcon));			}		case MATROXFB_SET_OUTPUT_CONNECTION:			{				u_int32_t tmp;				int out;				int changes;				if (get_user(tmp, (u_int32_t*)arg))					return -EFAULT;				for (out = 0; out < 32; out++) {					if (tmp & (1 << out)) {						if (out >= MATROXFB_MAX_OUTPUTS)							return -ENXIO;						if (!ACCESS_FBINFO(outputs[out]).output)							return -ENXIO;						switch (ACCESS_FBINFO(outputs[out]).src) {							case MATROXFB_SRC_NONE:							case MATROXFB_SRC_CRTC2:								break;							default:								return -EBUSY;						}					}				}				if (ACCESS_FBINFO(devflags.panellink)) {					if (tmp & MATROXFB_OUTPUT_CONN_DFP)						return -EINVAL;					if ((ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) && tmp)						return -EBUSY;				}				changes = 0;				for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {					if (tmp & (1 << out)) {						if (ACCESS_FBINFO(outputs[out]).src != MATROXFB_SRC_CRTC2) {							changes = 1;							ACCESS_FBINFO(outputs[out]).src = MATROXFB_SRC_CRTC2;						}					} else if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) {						changes = 1;						ACCESS_FBINFO(outputs[out]).src = MATROXFB_SRC_NONE;					}				}				if (!changes)					return 0;				matroxfb_dh_switch(m2info->currcon, info);				return 0;			}		case MATROXFB_GET_OUTPUT_CONNECTION:			{				u_int32_t conn = 0;				int out;				for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {					if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC2) {						conn |= 1 << out;					}				}				if (put_user(conn, (u_int32_t*)arg))					return -EFAULT;				return 0;			}		case MATROXFB_GET_AVAILABLE_OUTPUTS:			{				u_int32_t tmp = 0;				int out;				for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) {					if (ACCESS_FBINFO(outputs[out]).output) {						switch (ACCESS_FBINFO(outputs[out]).src) {							case MATROXFB_SRC_NONE:							case MATROXFB_SRC_CRTC2:								tmp |= 1 << out;								break;						}					}				}				if (ACCESS_FBINFO(devflags.panellink)) {					tmp &= ~MATROXFB_OUTPUT_CONN_DFP;					if (ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_CRTC1) {						tmp = 0;					}				}				if (put_user(tmp, (u_int32_t*)arg))					return -EFAULT;				return 0;			}	}	return -EINVAL;#undef m2info}static int matroxfb_dh_blank(int blank, struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	switch (blank) {		case 1:		case 2:		case 3:		case 4:		default:;	}	/* do something... */	return 0;#undef m2info}static void matroxfb_dh_blank24(int blank, struct fb_info* info) {	matroxfb_dh_blank(blank, info);}static struct fb_ops matroxfb_dh_ops = {	owner:		THIS_MODULE,	fb_open:	matroxfb_dh_open,	fb_release:	matroxfb_dh_release,	fb_get_fix:	matroxfb_dh_get_fix,	fb_get_var:	matroxfb_dh_get_var,	fb_set_var:	matroxfb_dh_set_var,	fb_get_cmap:	matroxfb_dh_get_cmap,	fb_set_cmap:	matroxfb_dh_set_cmap,	fb_pan_display:	matroxfb_dh_pan_display,	fb_ioctl:	matroxfb_dh_ioctl,};static int matroxfb_dh_switch(int con, struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	struct fb_cmap* cmap;	struct display* p;	if (m2info->currcon >= 0) {		cmap = &m2info->currcon_display->cmap;		if (cmap->len) {			fb_get_cmap(cmap, 1, matroxfb_dh_getcolreg, info);		}	}	m2info->currcon = con;	if (con < 0)		p = m2info->fbcon.disp;	else		p = fb_display + con;	m2info->currcon_display = p;	p->var.activate = FB_ACTIVATE_NOW;	matroxfb_dh_set_var(&p->var, con, info);	return 0;#undef m2info}static int matroxfb_dh_updatevar(int con, struct fb_info* info) {#define m2info (list_entry(info, struct matroxfb_dh_fb_info, fbcon))	matroxfb_dh_pan_var(m2info, &fb_display[con].var);	return 0;#undef m2info}static struct fb_var_screeninfo matroxfb_dh_defined = {		640,480,640,480,/* W,H, virtual W,H */		0,0,		/* offset */		32,		/* depth */		0,		/* gray */		{0,0,0},	/* R */		{0,0,0},	/* G */		{0,0,0},	/* B */		{0,0,0},	/* alpha */		0,		/* nonstd */		FB_ACTIVATE_NOW,		-1,-1,		/* display size */		0,		/* accel flags */		39721L,48L,16L,33L,10L,		96L,2,0,	/* no sync info */		FB_VMODE_NONINTERLACED,		{0,0,0,0,0,0}};static int matroxfb_dh_regit(CPMINFO struct matroxfb_dh_fb_info* m2info) {#define minfo (m2info->primary_dev)	struct display* d;	void* oldcrtc2;	d = kmalloc(sizeof(*d), GFP_KERNEL);	if (!d) {		return -ENOMEM;	}	memset(d, 0, sizeof(*d));	strcpy(m2info->fbcon.modename, "MATROX CRTC2");	m2info->fbcon.changevar = NULL;	m2info->fbcon.node = NODEV;	m2info->fbcon.fbops = &matroxfb_dh_ops;	m2info->fbcon.disp = d;	m2info->fbcon.switch_con = &matroxfb_dh_switch;	m2info->fbcon.updatevar = &matroxfb_dh_updatevar;	m2info->fbcon.blank = &matroxfb_dh_blank24;	m2info->fbcon.flags = FBINFO_FLAG_DEFAULT;	m2info->currcon = -1;	m2info->currcon_display = d;	if (mem < 64)		mem *= 1024;	if (mem < 64*1024)		mem *= 1024;	mem &= ~0x00000FFF;	/* PAGE_MASK? */	if (ACCESS_FBINFO(video.len_usable) + mem <= ACCESS_FBINFO(video.len))		m2info->video.offbase = ACCESS_FBINFO(video.len) - mem;	else if (ACCESS_FBINFO(video.len) < mem) {		kfree(d);		return -ENOMEM;	} else { /* check yres on first head... */		m2info->video.borrowed = mem;		ACCESS_FBINFO(video.len_usable) -= mem;		m2info->video.offbase = ACCESS_FBINFO(video.len_usable);	}	m2info->video.base = ACCESS_FBINFO(video.base) + m2info->video.offbase;	m2info->video.len = m2info->video.len_usable = m2info->video.len_maximum = mem;	m2info->video.vbase.vaddr = vaddr_va(ACCESS_FBINFO(video.vbase)) + m2info->video.offbase;	m2info->mmio.base = ACCESS_FBINFO(mmio.base);	m2info->mmio.vbase = ACCESS_FBINFO(mmio.vbase);	m2info->mmio.len = ACCESS_FBINFO(mmio.len);	/*	 *  If we have unused output, connect CRTC2 to it...	 */	if (ACCESS_FBINFO(outputs[1]).output &&	    ACCESS_FBINFO(outputs[1]).src == MATROXFB_SRC_NONE &&	    ACCESS_FBINFO(outputs[2]).src == MATROXFB_SRC_NONE) {		ACCESS_FBINFO(outputs[1]).src = MATROXFB_SRC_CRTC2;	}	matroxfb_dh_set_var(&matroxfb_dh_defined, -2, &m2info->fbcon);	if (register_framebuffer(&m2info->fbcon)) {		kfree(d);		return -ENXIO;	}	if (m2info->currcon < 0) {		matroxfb_dh_set_var(&matroxfb_dh_defined, -1, &m2info->fbcon);	}	down_write(&ACCESS_FBINFO(crtc2.lock));	oldcrtc2 = ACCESS_FBINFO(crtc2.info);	ACCESS_FBINFO(crtc2.info) = m2info;	up_write(&ACCESS_FBINFO(crtc2.lock));	if (oldcrtc2) {		printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 already present: %p\n",			oldcrtc2);	}	return 0;#undef minfo}/* ************************** */static int matroxfb_dh_registerfb(struct matroxfb_dh_fb_info* m2info) {#define minfo (m2info->primary_dev)	if (matroxfb_dh_regit(PMINFO m2info)) {		printk(KERN_ERR "matroxfb_crtc2: secondary head failed to register\n");		return -1;	}	printk(KERN_INFO "matroxfb_crtc2: secondary head of fb%u was registered as fb%u\n",		GET_FB_IDX(ACCESS_FBINFO(fbcon.node)), GET_FB_IDX(m2info->fbcon.node));	m2info->fbcon_registered = 1;	return 0;#undef minfo}static void matroxfb_dh_deregisterfb(struct matroxfb_dh_fb_info* m2info) {#define minfo (m2info->primary_dev)	if (m2info->fbcon_registered) {		int id;		struct matroxfb_dh_fb_info* crtc2;		down_write(&ACCESS_FBINFO(crtc2.lock));		crtc2 = ACCESS_FBINFO(crtc2.info);		if (crtc2 == m2info)			ACCESS_FBINFO(crtc2.info) = NULL;		up_write(&ACCESS_FBINFO(crtc2.lock));		if (crtc2 != m2info) {			printk(KERN_ERR "matroxfb_crtc2: Internal consistency check failed: crtc2 mismatch at unload: %p != %p\n",				crtc2, m2info);			printk(KERN_ERR "matroxfb_crtc2: Expect kernel crash after module unload.\n");			return;		}		id = GET_FB_IDX(m2info->fbcon.node);		unregister_framebuffer(&m2info->fbcon);		kfree(m2info->fbcon.disp);		/* return memory back to primary head */		ACCESS_FBINFO(video.len_usable) += m2info->video.borrowed;		printk(KERN_INFO "matroxfb_crtc2: fb%u unregistered\n", id);		m2info->fbcon_registered = 0;	}#undef minfo}static void* matroxfb_crtc2_probe(struct matrox_fb_info* minfo) {	struct matroxfb_dh_fb_info* m2info;	/* hardware is CRTC2 incapable... */	if (!ACCESS_FBINFO(devflags.crtc2))		return NULL;	m2info = (struct matroxfb_dh_fb_info*)kmalloc(sizeof(*m2info), GFP_KERNEL);	if (!m2info) {		printk(KERN_ERR "matroxfb_crtc2: Not enough memory for CRTC2 control structs\n");		return NULL;	}	memset(m2info, 0, sizeof(*m2info));	m2info->primary_dev = MINFO;	if (matroxfb_dh_registerfb(m2info)) {		kfree(m2info);		printk(KERN_ERR "matroxfb_crtc2: CRTC2 framebuffer failed to register\n");		return NULL;	}	return m2info;}static void matroxfb_crtc2_remove(struct matrox_fb_info* minfo, void* crtc2) {	matroxfb_dh_deregisterfb(crtc2);	kfree(crtc2);}static struct matroxfb_driver crtc2 = {		name:	"Matrox G400 CRTC2",		probe:	matroxfb_crtc2_probe,		remove:	matroxfb_crtc2_remove };static int matroxfb_crtc2_init(void) {	matroxfb_register_driver(&crtc2);	return 0;}static void matroxfb_crtc2_exit(void) {	matroxfb_unregister_driver(&crtc2);}MODULE_AUTHOR("(c) 1999-2002 Petr Vandrovec <vandrove@vc.cvut.cz>");MODULE_DESCRIPTION("Matrox G400 CRTC2 driver");MODULE_LICENSE("GPL");module_init(matroxfb_crtc2_init);module_exit(matroxfb_crtc2_exit);/* we do not have __setup() yet */

⌨️ 快捷键说明

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