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

📄 cyblafb.c

📁 Linux环境下视频显示卡设备的驱动程序源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	// enforce (h|v)sync_len limits	//	var->hsync_len &= ~7;	if(var->hsync_len > 248)		var->hsync_len = 248;	var->vsync_len &= 15;	//	// Enforce horizontal and vertical hardware limits.	// 1600x1200 is mentioned as a maximum, but higher resolutions could	// work with slow refresh, small margins and short sync.	//	var->xres &= ~7;	if (((var->xres + var->left_margin + var->right_margin +			var->hsync_len) > (bpp == 32 ? 2040 : 4088)) ||			((var->yres + var->upper_margin + var->lower_margin +			var->vsync_len) > 2047))		return -EINVAL;	if ((var->xres > 1600) || (var->yres > 1200))		output("Mode %dx%d exceeds documented limits.\n",					   var->xres, var->yres);	//	// try to be smart about (x|y)res_virtual problems.	//	if (var->xres > var->xres_virtual)		var->xres_virtual = var->xres;	if (var->yres > var->yres_virtual)		var->yres_virtual = var->yres;	if (bpp == 8 || bpp == 16) {		if (var->xres_virtual > 4088)			var->xres_virtual = 4088;	} else {		if (var->xres_virtual > 2040)			var->xres_virtual = 2040;	}	var->xres_virtual &= ~7;	while (var->xres_virtual * var->yres_virtual * bpp / 8 >	       info->fix.smem_len) {		if (var->yres_virtual > var->yres)			var->yres_virtual--;		else if (var->xres_virtual > var->xres)			var->xres_virtual -= 8;		else			return -EINVAL;	}	switch (bpp) {	case 8:		var->red.offset = 0;		var->green.offset = 0;		var->blue.offset = 0;		var->red.length = 6;		var->green.length = 6;		var->blue.length = 6;		break;	case 16:		var->red.offset = 11;		var->green.offset = 5;		var->blue.offset = 0;		var->red.length = 5;		var->green.length = 6;		var->blue.length = 5;		break;	case 32:		var->red.offset = 16;		var->green.offset = 8;		var->blue.offset = 0;		var->red.length = 8;		var->green.length = 8;		var->blue.length = 8;		break;	default:		return -EINVAL;	}	return 0;}//=====================================================================//// Pan the display//// The datasheets defines crt start address to be 20 bits wide and// to be programmed to CR0C, CR0D, CR1E and CR27. Actually there is// CR2B[5] as an undocumented extension bit. Epia BIOS 2.07 does use// it, so it is also safe to be used here. BTW: datasheet CR0E on page// 90 really is CR1E, the real CRE is documented on page 72.//// BUT://// As of internal version 0.60 we do not use vga panning any longer.// Vga panning did not allow us the use of all available video memory// and thus prevented ywrap scrolling. We do use the "right view"// register now.//////=====================================================================static int cyblafb_pan_display(struct fb_var_screeninfo *var,			       struct fb_info *info){	KD_GRAPHICS_RETURN(0);	info->var.xoffset = var->xoffset;	info->var.yoffset = var->yoffset;	out32(GE10, 0x80000000 | ((var->xoffset + (var->yoffset *		    var->xres_virtual)) * var->bits_per_pixel / 32));	return 0;}//============================================//// This will really help in case of a bug ...// dump most gaphics core registers.////============================================static void regdump(struct cyblafb_par *par){	int i;	if (verbosity < 2)		return;	printk("\n");	for (i = 0; i <= 0xff; i++) {		outb(i, 0x3d4);		printk("CR%02x=%02x ", i, inb(0x3d5));		if (i % 16 == 15)			printk("\n");	}	outb(0x30, 0x3ce);	outb(inb(0x3cf) | 0x40, 0x3cf);	for (i = 0; i <= 0x1f; i++) {		if (i == 0 || (i > 2 && i < 8) || i == 0x10 || i == 0x11		    || i == 0x16) {			outb(i, 0x3d4);			printk("CR%02x=%02x ", i, inb(0x3d5));		} else			printk("------- ");		if (i % 16 == 15)			printk("\n");	}	outb(0x30, 0x3ce);	outb(inb(0x3cf) & 0xbf, 0x3cf);	printk("\n");	for (i = 0; i <= 0x7f; i++) {		outb(i, 0x3ce);		printk("GR%02x=%02x ", i, inb(0x3cf));		if (i % 16 == 15)			printk("\n");	}	printk("\n");	for (i = 0; i <= 0xff; i++) {		outb(i, 0x3c4);		printk("SR%02x=%02x ", i, inb(0x3c5));		if (i % 16 == 15)			printk("\n");	}	printk("\n");	for (i = 0; i <= 0x1F; i++) {		inb(0x3da);	// next access is index!		outb(i, 0x3c0);		printk("AR%02x=%02x ", i, inb(0x3c1));		if (i % 16 == 15)			printk("\n");	}	printk("\n");	inb(0x3DA);		// reset internal flag to 3c0 index	outb(0x20, 0x3C0);	// enable attr	return;}//=======================================================================//// Save State//// This function is called while a switch to KD_TEXT is in progress,// before any of the other functions are called.////=======================================================================static void cyblafb_save_state(struct fb_info *info){	struct cyblafb_par *par = info->par;	if (verbosity > 0)		output("Switching to KD_TEXT\n");	disabled = 0;	regdump(par);	enable_mmio();	return;}//=======================================================================//// Restore State//// This function is called while a switch to KD_GRAPHICS is in progress,// We have to turn on vga style panning registers again because the// trident driver of X does not know about GE10.////=======================================================================static void cyblafb_restore_state(struct fb_info *info){	if (verbosity > 0)		output("Switching to KD_GRAPHICS\n");	out32(GE10, 0);	disabled = 1;	return;}//======================================//// Set hardware to requested video mode////======================================static int cyblafb_set_par(struct fb_info *info){	struct cyblafb_par *par = info->par;	u32 htotal, hdispend, hsyncstart, hsyncend, hblankstart,	    hblankend, preendfetch, vtotal, vdispend, vsyncstart,	    vsyncend, vblankstart, vblankend;	struct fb_var_screeninfo *var = &info->var;	int bpp = var->bits_per_pixel;	int i;	KD_GRAPHICS_RETURN(0);	if (verbosity > 0)		output("Switching to new mode: "		       "fbset -g %d %d %d %d %d -t %d %d %d %d %d %d %d\n",		       var->xres, var->yres, var->xres_virtual,		       var->yres_virtual, var->bits_per_pixel, var->pixclock,		       var->left_margin, var->right_margin, var->upper_margin,		       var->lower_margin, var->hsync_len, var->vsync_len);	htotal = (var->xres + var->left_margin + var->right_margin +		  var->hsync_len) / 8 - 5;	hdispend = var->xres / 8 - 1;	hsyncstart = (var->xres + var->right_margin) / 8;	hsyncend = var->hsync_len / 8;	hblankstart = hdispend + 1;	hblankend = htotal + 3; // should be htotal + 5, bios does it this way	preendfetch = ((var->xres >> 3) + 1) * ((bpp + 1) >> 3);	vtotal = var->yres + var->upper_margin + var->lower_margin +							var->vsync_len - 2;	vdispend = var->yres - 1;	vsyncstart = var->yres + var->lower_margin;	vblankstart = var->yres;	vblankend = vtotal; // should be vtotal + 2, but bios does it this way	vsyncend = var->vsync_len;	enable_mmio();		// necessary! ... check X ...	write3X4(CR11, read3X4(CR11) & 0x7F);	// unlock cr00 .. cr07	write3CE(GR30, 8);	if ((displaytype == DISPLAY_FP) && var->xres < nativex) {		// stretch or center ?		out8(0x3C2, 0xEB);		write3CE(GR30, read3CE(GR30) | 0x81);	// shadow mode on		if (center) {			write3CE(GR52, (read3CE(GR52) & 0x7C) | 0x80);			write3CE(GR53, (read3CE(GR53) & 0x7C) | 0x80);		} else if (stretch) {			write3CE(GR5D, 0);			write3CE(GR52, (read3CE(GR52) & 0x7C) | 1);			write3CE(GR53, (read3CE(GR53) & 0x7C) | 1);		}	} else {		out8(0x3C2, 0x2B);		write3CE(GR30, 8);	}	//	// Setup CRxx regs	//	write3X4(CR00, htotal & 0xFF);	write3X4(CR01, hdispend & 0xFF);	write3X4(CR02, hblankstart & 0xFF);	write3X4(CR03, hblankend & 0x1F);	write3X4(CR04, hsyncstart & 0xFF);	write3X4(CR05, (hsyncend & 0x1F) | ((hblankend & 0x20) << 2));	write3X4(CR06, vtotal & 0xFF);	write3X4(CR07, (vtotal & 0x100) >> 8 |		       (vdispend & 0x100) >> 7 |		       (vsyncstart & 0x100) >> 6 |		       (vblankstart & 0x100) >> 5 |		       0x10 |		       (vtotal & 0x200) >> 4 |		       (vdispend & 0x200) >> 3 | (vsyncstart & 0x200) >> 2);	write3X4(CR08, 0);	write3X4(CR09, (vblankstart & 0x200) >> 4 | 0x40 |	// FIX !!!		       ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0));	write3X4(CR0A, 0);	// Init to some reasonable default	write3X4(CR0B, 0);	// Init to some reasonable default	write3X4(CR0C, 0);	// Offset 0	write3X4(CR0D, 0);	// Offset 0	write3X4(CR0E, 0);	// Init to some reasonable default	write3X4(CR0F, 0);	// Init to some reasonable default	write3X4(CR10, vsyncstart & 0xFF);	write3X4(CR11, (vsyncend & 0x0F));	write3X4(CR12, vdispend & 0xFF);	write3X4(CR13, ((info->var.xres_virtual * bpp) / (4 * 16)) & 0xFF);	write3X4(CR14, 0x40);	// double word mode	write3X4(CR15, vblankstart & 0xFF);	write3X4(CR16, vblankend & 0xFF);	write3X4(CR17, 0xE3);	write3X4(CR18, 0xFF);	//	 CR19: needed for interlaced modes ... ignore it for now	write3X4(CR1A, 0x07);	// Arbitration Control Counter 1	write3X4(CR1B, 0x07);	// Arbitration Control Counter 2	write3X4(CR1C, 0x07);	// Arbitration Control Counter 3	write3X4(CR1D, 0x00);	// Don't know, doesn't hurt ; -)	write3X4(CR1E, (info->var.vmode & FB_VMODE_INTERLACED) ? 0x84 : 0x80);	//	 CR1F: do not set, contains BIOS info about memsize	write3X4(CR20, 0x20);	// enabe wr buf, disable 16bit planar mode	write3X4(CR21, 0x20);	// enable linear memory access	//	 CR22: RO cpu latch readback	//	 CR23: ???	//	 CR24: RO AR flag state	//	 CR25: RAMDAC rw timing, pclk buffer tristate control ????	//	 CR26: ???	write3X4(CR27, (vdispend & 0x400) >> 6 |		       (vsyncstart & 0x400) >> 5 |		       (vblankstart & 0x400) >> 4 |		       (vtotal & 0x400) >> 3 |		       0x8);	//	 CR28: ???	write3X4(CR29, (read3X4(CR29) & 0xCF) | ((((info->var.xres_virtual *			bpp) / (4 * 16)) & 0x300) >> 4));	write3X4(CR2A, read3X4(CR2A) | 0x40);	write3X4(CR2B, (htotal & 0x100) >> 8 |		       (hdispend & 0x100) >> 7 |		       // (0x00 & 0x100) >> 6 |   hinterlace para bit 8 ???		       (hsyncstart & 0x100) >> 5 |		       (hblankstart & 0x100) >> 4);	//	 CR2C: ???	//	 CR2D: initialized in cyblafb_setup_GE()	write3X4(CR2F, 0x92);	// conservative, better signal quality	//	 CR30: reserved	//	 CR31: reserved	//	 CR32: reserved	//	 CR33: reserved	//	 CR34: disabled in CR36	//	 CR35: disabled in CR36	//	 CR36: initialized in cyblafb_setup_GE	//	 CR37: i2c, ignore for now	write3X4(CR38, (bpp == 8) ? 0x00 :	//		       (bpp == 16) ? 0x05 :	// highcolor		       (bpp == 24) ? 0x29 :	// packed 24bit truecolor		       (bpp == 32) ? 0x09 : 0); // truecolor, 16 bit pixelbus	write3X4(CR39, 0x01 |	// MMIO enable		       (pcirb ? 0x02 : 0) |	// pci read burst enable		       (pciwb ? 0x04 : 0));	// pci write burst enable	write3X4(CR55, 0x1F | // pci clocks * 2 for STOP# during 1st data phase		       (pcirr ? 0x40 : 0) |	// pci read retry enable		       (pciwr ? 0x80 : 0));	// pci write retry enable	write3X4(CR56, preendfetch >> 8 < 2 ? (preendfetch >> 8 & 0x01) | 2					    : 0);	write3X4(CR57, preendfetch >> 8 < 2 ? preendfetch & 0xff : 0);	write3X4(CR58, 0x82);	// Bios does this .... don't know more	//	// Setup SRxx regs	//	write3C4(SR00, 3);	write3C4(SR01, 1);	//set char clock 8 dots wide	write3C4(SR02, 0x0F);	//enable 4 maps needed in chain4 mode	write3C4(SR03, 0);	//no character map select	write3C4(SR04, 0x0E);	//memory mode: ext mem, even, chain4	out8(0x3C4, 0x0b);	in8(0x3C5);		// Set NEW mode	write3C4(SR0D, 0x00);	// test ... check	set_vclk(par, (bpp == 32 ? 200000000 : 100000000)					/ info->var.pixclock);	//SR18, SR19	//	// Setup GRxx regs	//	write3CE(GR00, 0x00);	// test ... check	write3CE(GR01, 0x00);	// test ... check	write3CE(GR02, 0x00);	// test ... check	write3CE(GR03, 0x00);	// test ... check	write3CE(GR04, 0x00);	// test ... check	write3CE(GR05, 0x40);	// no CGA compat, allow 256 col	write3CE(GR06, 0x05);	// graphics mode	write3CE(GR07, 0x0F);	// planes?	write3CE(GR08, 0xFF);	// test ... check	write3CE(GR0F, (bpp == 32) ? 0x1A : 0x12); // vclk / 2 if 32bpp, chain4	write3CE(GR20, 0xC0);	// test ... check	write3CE(GR2F, 0xA0);	// PCLK = VCLK, no skew,	//	// Setup ARxx regs	//	for (i = 0; i < 0x10; i++)	// set AR00 .. AR0f		write3C0(i, i);	write3C0(AR10, 0x41);	// graphics mode and support 256 color modes	write3C0(AR12, 0x0F);	// planes	write3C0(AR13, 0);	// horizontal pel panning	in8(0x3DA);		// reset internal flag to 3c0 index	out8(0x3C0, 0x20);	// enable attr	//	// Setup hidden RAMDAC command register	//	in8(0x3C8);		// these reads are	in8(0x3C6);		// necessary to	in8(0x3C6);		// unmask the RAMDAC	in8(0x3C6);		// command reg, otherwise	in8(0x3C6);		// we would write the pixelmask reg!	out8(0x3C6, (bpp == 8) ? 0x00 : // 256 colors	     (bpp == 15) ? 0x10 :	//	     (bpp == 16) ? 0x30 :	// hicolor	     (bpp == 24) ? 0xD0 :	// truecolor	     (bpp == 32) ? 0xD0 : 0);	// truecolor	in8(0x3C8);	//	// GR31 is not mentioned in the datasheet	//	if (displaytype == DISPLAY_FP)		write3CE(GR31, (read3CE(GR31) & 0x8F) |			 ((info->var.yres > 1024) ? 0x50 :			  (info->var.yres > 768) ? 0x30 :			  (info->var.yres > 600) ? 0x20 :			  (info->var.yres > 480) ? 0x10 : 0));	info->fix.visual = (bpp == 8) ? FB_VISUAL_PSEUDOCOLOR				      : FB_VISUAL_TRUECOLOR;	info->fix.line_length = info->var.xres_virtual * (bpp >> 3);	info->cmap.len = (bpp == 8) ? 256 : 16;	//	// init acceleration engine	//	cyblafb_setup_GE(info->var.xres_virtual, info->var.bits_per_pixel);	//	// Set/clear flags to allow proper scroll mode selection.	//	if (var->xres == var->xres_virtual)		info->flags &= ~FBINFO_HWACCEL_XPAN;	else		info->flags |= FBINFO_HWACCEL_XPAN;	if (var->yres == var->yres_virtual)		info->flags &= ~FBINFO_HWACCEL_YPAN;	else		info->flags |= FBINFO_HWACCEL_YPAN;	if (info->fix.smem_len !=	    var->xres_virtual * var->yres_virtual * bpp / 8)		info->flags &= ~FBINFO_HWACCEL_YWRAP;	else		info->flags |= FBINFO_HWACCEL_YWRAP;	regdump(par);	return 0;}//========================//// Set one color register////========================static int cyblafb_setcolreg(unsigned regno, unsigned red, unsigned green,			     unsigned blue, unsigned transp,			     struct fb_info *info){	int bpp = info->var.bits_per_pixel;	KD_GRAPHICS_RETURN(0);	if (regno >= info->cmap.len)		return 1;	if (bpp == 8) {		out8(0x3C6, 0xFF);		out8(0x3C8, regno);		out8(0x3C9, red >> 10);		out8(0x3C9, green >> 10);		out8(0x3C9, blue >> 10);	} else if (regno < 16) {		if (bpp == 16)	// RGB 565			((u32 *) info->pseudo_palette)[regno] =				(red & 0xF800) |				((green & 0xFC00) >> 5) |				((blue & 0xF800) >> 11);		else if (bpp == 32)	// ARGB 8888			((u32 *) info->pseudo_palette)[regno] =				((transp & 0xFF00) << 16) |				((red & 0xFF00) << 8) |				((green & 0xFF00)) | ((blue & 0xFF00) >> 8);	}	return 0;}//==========================================================//// Try blanking the screen. For flat panels it does nothing////==========================================================static int cyblafb_blank(int blank_mode, struct fb_info *info){	unsigned char PMCont, DPMSCont;	KD_GRAPHICS_RETURN(0);	if (displaytype == DISPLAY_FP)		return 0;	out8(0x83C8, 0x04);	// DPMS Control	PMCont = in8(0x83C6) & 0xFC;	DPMSCont = read3CE(GR23) & 0xFC;	switch (blank_mode) {	case FB_BLANK_UNBLANK:	// Screen: On, HSync: On, VSync: On	case FB_BLANK_NORMAL:	// Screen: Off, HSync: On, VSync: On		PMCont |= 0x03;		DPMSCont |= 0x00;		break;	case FB_BLANK_HSYNC_SUSPEND:	// Screen: Off, HSync: Off, VSync: On		PMCont |= 0x02;		DPMSCont |= 0x01;		break;	case FB_BLANK_VSYNC_SUSPEND:	// Screen: Off, HSync: On, VSync: Off		PMCont |= 0x02;		DPMSCont |= 0x02;		break;	case FB_BLANK_POWERDOWN:	// Screen: Off, HSync: Off, VSync: Off		PMCont |= 0x00;		DPMSCont |= 0x03;		break;

⌨️ 快捷键说明

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