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

📄 sis_main.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
static intsisfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,		unsigned transp, struct fb_info *info){	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;	if(regno >= sisfb_get_cmap_len(&info->var))		return 1;	switch(info->var.bits_per_pixel) {	case 8:		outSISREG(SISDACA, regno);		outSISREG(SISDACD, (red >> 10));		outSISREG(SISDACD, (green >> 10));		outSISREG(SISDACD, (blue >> 10));		if(ivideo->currentvbflags & VB_DISPTYPE_DISP2) {			outSISREG(SISDAC2A, regno);			outSISREG(SISDAC2D, (red >> 8));			outSISREG(SISDAC2D, (green >> 8));			outSISREG(SISDAC2D, (blue >> 8));		}		break;	case 16:		((u32 *)(info->pseudo_palette))[regno] =				(red & 0xf800)          |				((green & 0xfc00) >> 5) |				((blue & 0xf800) >> 11);		break;	case 32:		red >>= 8;		green >>= 8;		blue >>= 8;		((u32 *)(info->pseudo_palette))[regno] =				(red << 16) | (green << 8) | (blue);		break;	}	return 0;}static intsisfb_set_par(struct fb_info *info){	int err;	if((err = sisfb_do_set_var(&info->var, 1, info)))		return err;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)	sisfb_get_fix(&info->fix, info->currcon, info);#else	sisfb_get_fix(&info->fix, -1, info);#endif	return 0;}static intsisfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info){	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;	unsigned int htotal = 0, vtotal = 0, myrateindex = 0;	unsigned int drate = 0, hrate = 0, maxyres;	int found_mode = 0;	int refresh_rate, search_idx, tidx;	BOOLEAN recalc_clock = FALSE;	u32 pixclock;	htotal = var->left_margin + var->xres + var->right_margin + var->hsync_len;	vtotal = var->upper_margin + var->lower_margin + var->vsync_len;	pixclock = var->pixclock;	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {		vtotal += var->yres;		vtotal <<= 1;	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {		vtotal += var->yres;		vtotal <<= 2;	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {		vtotal += var->yres;		vtotal <<= 1;	} else		vtotal += var->yres;	if(!(htotal) || !(vtotal)) {		SISFAIL("sisfb: no valid timing data");	}	search_idx = 0;	while( (sisbios_mode[search_idx].mode_no[0] != 0) &&	       (sisbios_mode[search_idx].xres <= var->xres) ) {		if( (sisbios_mode[search_idx].xres == var->xres) &&		    (sisbios_mode[search_idx].yres == var->yres) &&		    (sisbios_mode[search_idx].bpp == var->bits_per_pixel)) {			if((tidx = sisfb_validate_mode(ivideo, search_idx,						ivideo->currentvbflags)) > 0) {				found_mode = 1;				search_idx = tidx;				break;			}		}		search_idx++;	}	if(!found_mode) {		search_idx = 0;		while(sisbios_mode[search_idx].mode_no[0] != 0) {		   if( (var->xres <= sisbios_mode[search_idx].xres) &&		       (var->yres <= sisbios_mode[search_idx].yres) &&		       (var->bits_per_pixel == sisbios_mode[search_idx].bpp) ) {			if((tidx = sisfb_validate_mode(ivideo,search_idx,						ivideo->currentvbflags)) > 0) {				found_mode = 1;				search_idx = tidx;				break;			}		   }		   search_idx++;		}		if(found_mode) {			printk(KERN_DEBUG				"sisfb: Adapted from %dx%dx%d to %dx%dx%d\n",				var->xres, var->yres, var->bits_per_pixel,				sisbios_mode[search_idx].xres,				sisbios_mode[search_idx].yres,				var->bits_per_pixel);			var->xres = sisbios_mode[search_idx].xres;			var->yres = sisbios_mode[search_idx].yres;		} else {			printk(KERN_ERR				"sisfb: Failed to find supported mode near %dx%dx%d\n",				var->xres, var->yres, var->bits_per_pixel);			return -EINVAL;		}	}	if( ((ivideo->vbflags2 & VB2_LVDS) ||	     ((ivideo->vbflags2 & VB2_30xBDH) && (ivideo->currentvbflags & CRT2_LCD))) &&	    (var->bits_per_pixel == 8) ) {		/* Slave modes on LVDS and 301B-DH */		refresh_rate = 60;		recalc_clock = TRUE;	} else if( (ivideo->current_htotal == htotal) &&		   (ivideo->current_vtotal == vtotal) &&		   (ivideo->current_pixclock == pixclock) ) {		/* x=x & y=y & c=c -> assume depth change */		drate = 1000000000 / pixclock;		hrate = (drate * 1000) / htotal;		refresh_rate = (unsigned int) (hrate * 2 / vtotal);	} else if( ( (ivideo->current_htotal != htotal) ||		     (ivideo->current_vtotal != vtotal) ) &&		   (ivideo->current_pixclock == var->pixclock) ) {		/* x!=x | y!=y & c=c -> invalid pixclock */		if(ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]]) {			refresh_rate =				ivideo->sisfb_lastrates[sisbios_mode[search_idx].mode_no[ivideo->mni]];		} else if(ivideo->sisfb_parm_rate != -1) {			/* Sic, sisfb_parm_rate - want to know originally desired rate here */			refresh_rate = ivideo->sisfb_parm_rate;		} else {			refresh_rate = 60;		}		recalc_clock = TRUE;	} else if((pixclock) && (htotal) && (vtotal)) {		drate = 1000000000 / pixclock;		hrate = (drate * 1000) / htotal;		refresh_rate = (unsigned int) (hrate * 2 / vtotal);	} else if(ivideo->current_refresh_rate) {		refresh_rate = ivideo->current_refresh_rate;		recalc_clock = TRUE;	} else {		refresh_rate = 60;		recalc_clock = TRUE;	}	myrateindex = sisfb_search_refresh_rate(ivideo, refresh_rate, search_idx);	/* Eventually recalculate timing and clock */	if(recalc_clock) {		if(!myrateindex) myrateindex = sisbios_mode[search_idx].rate_idx;		var->pixclock = (u32) (1000000000 / sisfb_mode_rate_to_dclock(&ivideo->SiS_Pr,						sisbios_mode[search_idx].mode_no[ivideo->mni],						myrateindex));		sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr,					sisbios_mode[search_idx].mode_no[ivideo->mni],					myrateindex, var);		if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {			var->pixclock <<= 1;		}	}	if(ivideo->sisfb_thismonitor.datavalid) {		if(!sisfb_verify_rate(ivideo, &ivideo->sisfb_thismonitor, search_idx,				myrateindex, refresh_rate)) {			printk(KERN_INFO				"sisfb: WARNING: Refresh rate exceeds monitor specs!\n");		}	}	/* Adapt RGB settings */	sisfb_bpp_to_var(ivideo, var);	/* Sanity check for offsets */	if(var->xoffset < 0) var->xoffset = 0;	if(var->yoffset < 0) var->yoffset = 0;	if(var->xres > var->xres_virtual)		var->xres_virtual = var->xres;	if(ivideo->sisfb_ypan) {		maxyres = sisfb_calc_maxyres(ivideo, var);		if(ivideo->sisfb_max) {			var->yres_virtual = maxyres;		} else {			if(var->yres_virtual > maxyres) {				var->yres_virtual = maxyres;			}		}		if(var->yres_virtual <= var->yres) {			var->yres_virtual = var->yres;		}	} else {		if(var->yres != var->yres_virtual) {			var->yres_virtual = var->yres;		}		var->xoffset = 0;		var->yoffset = 0;	}	/* Truncate offsets to maximum if too high */	if(var->xoffset > var->xres_virtual - var->xres) {		var->xoffset = var->xres_virtual - var->xres - 1;	}	if(var->yoffset > var->yres_virtual - var->yres) {		var->yoffset = var->yres_virtual - var->yres - 1;	}	/* Set everything else to 0 */	var->red.msb_right =		var->green.msb_right =		var->blue.msb_right =		var->transp.offset =		var->transp.length =		var->transp.msb_right = 0;	return 0;}static intsisfb_pan_display(struct fb_var_screeninfo *var, struct fb_info* info){	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;	int err;	if(var->xoffset > (var->xres_virtual - var->xres))		return -EINVAL;	if(var->yoffset > (var->yres_virtual - var->yres))		return -EINVAL;	if(var->vmode & FB_VMODE_YWRAP)		return -EINVAL;	if(var->xoffset + info->var.xres > info->var.xres_virtual ||	   var->yoffset + info->var.yres > info->var.yres_virtual)		return -EINVAL;	if((err = sisfb_pan_var(ivideo, var)) < 0)		return err;	info->var.xoffset = var->xoffset;	info->var.yoffset = var->yoffset;	return 0;}static intsisfb_blank(int blank, struct fb_info *info){	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;	return sisfb_myblank(ivideo, blank);}#endif/* ----------- FBDev related routines for all series ---------- */static intsisfb_ioctl(struct inode *inode, struct file *file,            unsigned int cmd, unsigned long arg,#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	    int con,#endif	    struct fb_info *info){	struct sis_video_info	*ivideo = (struct sis_video_info *)info->par;	struct sis_memreq	sismemreq;	struct fb_vblank	sisvbblank;	u32			gpu32 = 0;#ifndef __user#define __user#endif	u32 __user 		*argp = (u32 __user *)arg;	switch(cmd) {	   case FBIO_ALLOC:		if(!capable(CAP_SYS_RAWIO))			return -EPERM;		if(copy_from_user(&sismemreq, (void __user *)arg, sizeof(sismemreq)))			return -EFAULT;		sis_malloc(&sismemreq);		if(copy_to_user((void __user *)arg, &sismemreq, sizeof(sismemreq))) {			sis_free((u32)sismemreq.offset);			return -EFAULT;		}		break;	   case FBIO_FREE:		if(!capable(CAP_SYS_RAWIO))			return -EPERM;		if(get_user(gpu32, argp))			return -EFAULT;		sis_free(gpu32);		break;	   case FBIOGET_VBLANK:		sisvbblank.count = 0;		sisvbblank.flags = sisfb_setupvbblankflags(ivideo, &sisvbblank.vcount, &sisvbblank.hcount);		if(copy_to_user((void __user *)arg, &sisvbblank, sizeof(sisvbblank)))			return -EFAULT;		break;	   case SISFB_GET_INFO_SIZE:		return put_user(sizeof(struct sisfb_info), argp);	   case SISFB_GET_INFO_OLD:		if(ivideo->warncount++ < 10)			printk(KERN_INFO				"sisfb: Deprecated ioctl call received - update your application!\n");	   case SISFB_GET_INFO:  /* For communication with X driver */		ivideo->sisfb_infoblock.sisfb_id         = SISFB_ID;		ivideo->sisfb_infoblock.sisfb_version    = VER_MAJOR;		ivideo->sisfb_infoblock.sisfb_revision   = VER_MINOR;		ivideo->sisfb_infoblock.sisfb_patchlevel = VER_LEVEL;		ivideo->sisfb_infoblock.chip_id = ivideo->chip_id;		ivideo->sisfb_infoblock.sisfb_pci_vendor = ivideo->chip_vendor;		ivideo->sisfb_infoblock.memory = ivideo->video_size / 1024;		ivideo->sisfb_infoblock.heapstart = ivideo->heapstart / 1024;		if(ivideo->modechanged) {			ivideo->sisfb_infoblock.fbvidmode = ivideo->mode_no;		} else {			ivideo->sisfb_infoblock.fbvidmode = ivideo->modeprechange;		}		ivideo->sisfb_infoblock.sisfb_caps = ivideo->caps;		ivideo->sisfb_infoblock.sisfb_tqlen = ivideo->cmdQueueSize / 1024;		ivideo->sisfb_infoblock.sisfb_pcibus = ivideo->pcibus;		ivideo->sisfb_infoblock.sisfb_pcislot = ivideo->pcislot;		ivideo->sisfb_infoblock.sisfb_pcifunc = ivideo->pcifunc;		ivideo->sisfb_infoblock.sisfb_lcdpdc = ivideo->detectedpdc;		ivideo->sisfb_infoblock.sisfb_lcdpdca = ivideo->detectedpdca;		ivideo->sisfb_infoblock.sisfb_lcda = ivideo->detectedlcda;		ivideo->sisfb_infoblock.sisfb_vbflags = ivideo->vbflags;		ivideo->sisfb_infoblock.sisfb_currentvbflags = ivideo->currentvbflags;		ivideo->sisfb_infoblock.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;		ivideo->sisfb_infoblock.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;		ivideo->sisfb_infoblock.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;		ivideo->sisfb_infoblock.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;		ivideo->sisfb_infoblock.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;		ivideo->sisfb_infoblock.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;		ivideo->sisfb_infoblock.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;		ivideo->sisfb_infoblock.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;		ivideo->sisfb_infoblock.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);		ivideo->sisfb_infoblock.sisfb_tvypos = (u16)(ivideo->tvypos + 32);		ivideo->sisfb_infoblock.sisfb_heapsize = ivideo->sisfb_heap_size / 1024;		ivideo->sisfb_infoblock.sisfb_videooffset = ivideo->video_offset;		ivideo->sisfb_infoblock.sisfb_curfstn = ivideo->curFSTN;		ivideo->sisfb_infoblock.sisfb_curdstn = ivideo->curDSTN;		ivideo->sisfb_infoblock.sisfb_vbflags2 = ivideo->vbflags2;		ivideo->sisfb_infoblock.sisfb_can_post = ivideo->sisfb_can_post ? 1 : 0;		ivideo->sisfb_infoblock.sisfb_card_posted = ivideo->sisfb_card_posted ? 1 : 0;		ivideo->sisfb_infoblock.sisfb_was_boot_device = ivideo->sisfb_was_boot_device ? 1 : 0;		if(copy_to_user((void __user *)arg, &ivideo->sisfb_infoblock,						sizeof(ivideo->sisfb_infoblock)))			return -EFAULT;	        break;	   case SISFB_GET_VBRSTATUS_OLD:		if(ivideo->warncount++ < 10)			printk(KERN_INFO				"sisfb: Deprecated ioctl call received - update your application!\n");	   case SISFB_GET_VBRSTATUS:		if(sisfb_CheckVBRetrace(ivideo))			return put_user((u32)1, argp);		else			return put_user((u32)0, argp);	   case SISFB_GET_AUTOMAXIMIZE_OLD:		if(ivideo->warncount++ < 10)			printk(KERN_INFO				"sisfb: Deprecated ioctl call received - update your application!\n");	   case SISFB_GET_AUTOMAXIMIZE:		if(ivideo->sisfb_max)			return put_user((u32)1, argp);		else			return put_user((u32)0, argp);	   case SISFB_SET_AUTOMAXIMIZE_OLD:		if(ivideo->warncount++ < 10)			printk(KERN_INFO				"sisfb: Deprecated ioctl call received - update your application!\n");	   case SISFB_SET_AUTOMAXIMIZE:		if(get_user(gpu32, argp))			return -EFAULT;		ivideo->sisfb_max = (gpu32) ? 1 : 0;		break;	   case SISFB_SET_TVPOSOFFSET:		if(get_user(gpu32, argp))			return -EFAULT;		sisfb_set_TVxposoffset(ivideo, ((int)(gpu32 >> 16)) - 32);		sisfb_set_TVyposoffset(ivideo, ((int)(gpu32 & 0xffff)) - 32);		break;	   case SISFB_GET_TVPOSOFFSET:		return put_user((u32)(((ivideo->tvxpos+32)<<16)|((ivideo->tvypos+32)&0xffff)),							argp);	   case SISFB_COMMAND:		if(copy_from_user(&ivideo->sisfb_command, (void __user *)arg,							sizeof(struct sisfb_cmd)))			return -EFAULT;		sisfb_handle_command(ivideo, &ivideo->sisfb_command);		if(copy_to_user((void __user *)arg, &ivideo->sisfb_command,							sizeof(struct sisfb_cmd)))			return -EFAULT;		break;	   case SISFB_SET_LOCK:		if(get_user(gpu32, argp))			return -EFAULT;		ivideo->sisfblocked = (gpu32) ? 1 : 0;		break;	   default:#ifdef SIS_NEW_CONFIG_COMPAT		return -ENOIOCTLCMD;#else		return -EINVAL;#endif	}	return 0;}#ifdef SIS_NEW_CONFIG_COMPATstatic longsisfb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg, struct fb_info *info){	int ret;	lock_kernel();	ret = sisfb_ioctl(NULL, f, cmd, arg, info);	unlock_kernel();	return ret;}#endifstatic int

⌨️ 快捷键说明

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