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

📄 sis_main.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		drate = 1000000000 / pixclock;	        hrate = (drate * 1000) / htotal;	        refresh_rate = (unsigned int) (hrate * 2 / vtotal);	} else if( ( (ivideo->current_htotal != htotal) ||	/* x!=x | y!=y & c=c -> invalid pixclock */	    	     (ivideo->current_vtotal != vtotal) ) &&	    	   (ivideo->current_pixclock == var->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,	   					&ivideo->sishw_ext,						sisbios_mode[search_idx].mode_no[ivideo->mni],						myrateindex));	   sisfb_mode_rate_to_ddata(&ivideo->SiS_Pr, &ivideo->sishw_ext,		 		    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;	sisfb_info        	x;	u32			gpu32 = 0;	static int 		count = 0;	u32 __user		*argp = (u32 __user *) arg;	switch (cmd) {	   case FBIO_ALLOC:		if(!capable(CAP_SYS_RAWIO)) {			return -EPERM;		}		if(copy_from_user(&sismemreq, argp, sizeof(sismemreq))) {		   	return -EFAULT;		}        	sis_malloc(&sismemreq);		if(copy_to_user(argp, &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(argp, &sisvbblank, sizeof(sisvbblank))) {			return -EFAULT;		}		break;	   case SISFB_GET_INFO_SIZE:	        return put_user(sizeof(sisfb_info), argp);	   case SISFB_GET_INFO_OLD:	        if(++count < 50) {	           printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");		}	   case SISFB_GET_INFO:  /* For communication with X driver */		x.sisfb_id         = SISFB_ID;		x.sisfb_version    = VER_MAJOR;		x.sisfb_revision   = VER_MINOR;		x.sisfb_patchlevel = VER_LEVEL;		x.chip_id = ivideo->chip_id;		x.memory = ivideo->video_size / 1024;		x.heapstart = ivideo->heapstart / 1024;		if(ivideo->modechanged) {		   x.fbvidmode = ivideo->mode_no;		} else {		   x.fbvidmode = ivideo->modeprechange;		}		x.sisfb_caps = ivideo->caps;		x.sisfb_tqlen = 512; /* yet fixed */		x.sisfb_pcibus = ivideo->pcibus;		x.sisfb_pcislot = ivideo->pcislot;		x.sisfb_pcifunc = ivideo->pcifunc;		x.sisfb_lcdpdc = ivideo->detectedpdc;		x.sisfb_lcdpdca = ivideo->detectedpdca;		x.sisfb_lcda = ivideo->detectedlcda;		x.sisfb_vbflags = ivideo->vbflags;		x.sisfb_currentvbflags = ivideo->currentvbflags;		x.sisfb_scalelcd = ivideo->SiS_Pr.UsePanelScaler;		x.sisfb_specialtiming = ivideo->SiS_Pr.SiS_CustomT;		x.sisfb_haveemi = ivideo->SiS_Pr.HaveEMI ? 1 : 0;		x.sisfb_haveemilcd = ivideo->SiS_Pr.HaveEMILCD ? 1 : 0;		x.sisfb_emi30 = ivideo->SiS_Pr.EMI_30;		x.sisfb_emi31 = ivideo->SiS_Pr.EMI_31;		x.sisfb_emi32 = ivideo->SiS_Pr.EMI_32;		x.sisfb_emi33 = ivideo->SiS_Pr.EMI_33;		x.sisfb_tvxpos = (u16)(ivideo->tvxpos + 32);		x.sisfb_tvypos = (u16)(ivideo->tvypos + 32);		if(copy_to_user(argp, &x, sizeof(x))) {			return -EFAULT;		}	        break;	   case SISFB_GET_VBRSTATUS_OLD:	   	if(++count < 50) {	           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(++count < 50) {	           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(++count < 50) {		   printk(KERN_INFO "sisfb: Deprecated ioctl call received - update your application!\n");		}	   case SISFB_SET_AUTOMAXIMIZE:		if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {			return -EFAULT;		}		ivideo->sisfb_max = (gpu32) ? 1 : 0;		break;	   case SISFB_SET_TVPOSOFFSET:		if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {			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_SET_LOCK:		if(copy_from_user(&gpu32, argp, sizeof(gpu32))) {			return -EFAULT;		}		ivideo->sisfblocked = (gpu32) ? 1 : 0;		break;	   default:		return -EINVAL;	}	return 0;}static intsisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){	struct sis_video_info *ivideo = (struct sis_video_info *)info->par;	memset(fix, 0, sizeof(struct fb_fix_screeninfo));	strcpy(fix->id, ivideo->myid);	fix->smem_start  = ivideo->video_base;	fix->smem_len    = ivideo->sisfb_mem;	fix->type        = FB_TYPE_PACKED_PIXELS;	fix->type_aux    = 0;	fix->visual      = (ivideo->video_bpp == 8) ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;	fix->xpanstep    = 1;	fix->ypanstep 	 = (ivideo->sisfb_ypan) ? 1 : 0;	fix->ywrapstep   = 0;	fix->line_length = ivideo->video_linelength;	fix->mmio_start  = ivideo->mmio_base;	fix->mmio_len    = ivideo->mmio_size;	if(ivideo->sisvga_engine == SIS_300_VGA) {	   fix->accel    = FB_ACCEL_SIS_GLAMOUR;	} else if((ivideo->chip == SIS_330) || (ivideo->chip == SIS_760)) {	   fix->accel    = FB_ACCEL_SIS_XABRE;	} else {	   fix->accel    = FB_ACCEL_SIS_GLAMOUR_2;	}	return 0;}/* ----------------  fb_ops structures ----------------- */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static struct fb_ops sisfb_ops = {	.owner		= THIS_MODULE,	.fb_get_fix	= sisfb_get_fix,	.fb_get_var	= sisfb_get_var,	.fb_set_var	= sisfb_set_var,	.fb_get_cmap	= sisfb_get_cmap,	.fb_set_cmap	= sisfb_set_cmap,        .fb_pan_display = sisfb_pan_display,	.fb_ioctl	= sisfb_ioctl};#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)static struct fb_ops sisfb_ops = {	.owner          = THIS_MODULE,	.fb_open        = sisfb_open,	.fb_release     = sisfb_release,	.fb_check_var   = sisfb_check_var,	.fb_set_par     = sisfb_set_par,	.fb_setcolreg   = sisfb_setcolreg,        .fb_pan_display = sisfb_pan_display,        .fb_blank       = sisfb_blank,	.fb_fillrect    = fbcon_sis_fillrect,	.fb_copyarea    = fbcon_sis_copyarea,	.fb_imageblit   = cfb_imageblit,	.fb_cursor      = soft_cursor,	.fb_sync        = fbcon_sis_sync,	.fb_ioctl       = sisfb_ioctl};#endif/* ---------------- Chip generation dependent routines ---------------- */static struct pci_dev * sisfb_get_northbridge(int basechipid){	struct pci_dev *pdev = NULL;	int nbridgenum, nbridgeidx, i;	const unsigned short nbridgeids[] = {		PCI_DEVICE_ID_SI_540,	/* for SiS 540 VGA */		PCI_DEVICE_ID_SI_630,	/* for SiS 630/730 VGA */		PCI_DEVICE_ID_SI_730,		PCI_DEVICE_ID_SI_550,   /* for SiS 550 VGA */		PCI_DEVICE_ID_SI_650,   /* for SiS 650/651/740 VGA */		PCI_DEVICE_ID_SI_651,		PCI_DEVICE_ID_SI_740,		PCI_DEVICE_ID_SI_661,	/* for SiS 661/741/660/760 VGA */		PCI_DEVICE_ID_SI_741,		PCI_DEVICE_ID_SI_660,		PCI_DEVICE_ID_SI_760	};    	switch(basechipid) {#ifdef CONFIG_FB_SIS_300	case SIS_540:	nbridgeidx = 0; nbridgenum = 1; break;	case SIS_630:	nbridgeidx = 1; nbridgenum = 2; break;#endif#ifdef CONFIG_FB_SIS_315	case SIS_550:   nbridgeidx = 3; nbridgenum = 1; break;	case SIS_650:	nbridgeidx = 4; nbridgenum = 3; break;	case SIS_660:	nbridgeidx = 7; nbridgenum = 4; break;#endif	default:	return NULL;	}	for(i = 0; i < nbridgenum; i++) {		if((pdev = pci_find_device(PCI_VENDOR_ID_SI, nbridgeids[nbridgeidx+i], NULL))) break;	}	return pdev;}static int __devinit sisfb_get_dram_size(struct sis_video_info *ivideo){#if defined(CONFIG_FB_SIS_300) || defined(CONFIG_FB_SIS_315)	u8 reg;#endif	ivideo->video_size = 0;	switch(ivideo->chip) {#ifdef CONFIG_FB_SIS_300	case SIS_300:	        inSISIDXREG(SISSR, 0x14, reg);		ivideo->video_size = ((reg & 0x3F) + 1) << 20;		break;	case SIS_540:	case SIS_630:	case SIS_730:	   	if(!ivideo->nbridge) return -1;	   	pci_read_config_byte(ivideo->nbridge, 0x63, &reg);		ivideo->video_size = 1 << (((reg & 0x70) >> 4) + 21);		break;#endif#ifdef CONFIG_FB_SIS_315	case SIS_315H:	case SIS_315PRO:	case SIS_315:	   	inSISIDXREG(SISSR, 0x14, reg);		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;		switch((reg >> 2) & 0x03) {		case 0x01:		case 0x03:		   ivideo->video_size <<= 1;		   break;		case 0x02:		   ivideo->video_size += (ivideo->video_size/2);		}	   	break;	case SIS_330:	   	inSISIDXREG(SISSR, 0x14, reg);		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;		if(reg & 0x0c) ivideo->video_size <<= 1;	   	break;	case SIS_550:	case SIS_650:	case SIS_740:	    	inSISIDXREG(SISSR, 0x14, reg);		ivideo->video_size = (((reg & 0x3f) + 1) << 2) << 20;		break;	case SIS_661:	case SIS_741:	     	inSISIDXREG(SISCR, 0x79, reg);		ivideo->video_size = (1 << ((reg & 0xf0) >> 4)) << 20;	   	break;	case SIS_660:	case SIS_760:		inSISIDXREG(SISCR, 0x79, reg);		reg = (reg & 0xf0) >> 4;		if(reg)	ivideo->video_size = (1 << reg) << 20;		inSISIDXREG(SISCR, 0x78, reg);		reg &= 0x30;		if(reg) {		   if(reg == 0x10) ivideo->video_size += (32 << 20);		   else		   ivideo->video_size += (64 << 20);		}	   	break;#endif	default:		return -1;	}	return 0;}/* -------------- video bridge device detection --------------- */static void __devinit sisfb_detect_VB_connect(struct sis_video_info *ivideo){	u8 cr32, temp;#ifdef CONF

⌨️ 快捷键说明

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