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

📄 sis_main.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 5 页
字号:
	var->xres = var->xres_virtual = E * 8;	var->left_margin = D * 8;	var->right_margin = F * 8;	var->hsync_len = C * 8;	var->activate = FB_ACTIVATE_NOW;	var->sync = 0;	mr_data = inSISREG(SISMISCR);#if 0	mr_data = vgarb(0x1C);#endif	if (mr_data & 0x80)		var->sync &= ~FB_SYNC_VERT_HIGH_ACT;	else		var->sync |= FB_SYNC_VERT_HIGH_ACT;	if (mr_data & 0x40)		var->sync &= ~FB_SYNC_HOR_HIGH_ACT;	else		var->sync |= FB_SYNC_HOR_HIGH_ACT;	VT += 2;	VT <<= 1;	HT = (HT + 5) * 8;	hrate = (double) ivideo.refresh_rate * (double) VT / 2;	drate = hrate * HT;	var->pixclock = (u32) (1E12 / drate);#ifdef SISFB_PAN	if(sisfb_ypan) {	    var->yres_virtual = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));	    if(var->yres_virtual <= var->yres) {	        var->yres_virtual = var->yres;	    }	} else#endif	   var->yres_virtual = var->yres;        TWDEBUG("end of crtc_to_var");}/* ------------------ Public Routines -------------------------------- *//* -------- functions only for for 2.4 series ------- */#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)static int sisfb_set_var(struct fb_var_screeninfo *var, int con,			 struct fb_info *info){#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#define currcon info->currcon#endif	int err;	unsigned int cols, rows;	fb_display[con].var.activate = FB_ACTIVATE_NOW;        if(sisfb_do_set_var(var, con == currcon, info)) {		sisfb_crtc_to_var(var);		return -EINVAL;	}	sisfb_crtc_to_var(var);	sisfb_set_disp(con, var, info);	if(info->changevar)		(*info->changevar) (con);	if((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0)))		return err;	sisfb_do_install_cmap(con, info);	cols = sisbios_mode[sisfb_mode_idx].cols;	rows = sisbios_mode[sisfb_mode_idx].rows;	vc_resize_con(rows, cols, fb_display[con].conp->vc_num);	return 0;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#undef currcon#endif}static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,			  struct fb_info *info){#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#define currcon info->currcon#endif        if (con == currcon)		return fb_get_cmap(cmap, kspc, sis_getcolreg, info);	else if (fb_display[con].cmap.len)		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);	else		fb_copy_cmap(fb_default_cmap(ivideo.video_cmap_len), cmap, kspc ? 0 : 2);	return 0;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#undef currcon#endif}static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,			  struct fb_info *info){	int err;	if (!fb_display[con].cmap.len) {		err = fb_alloc_cmap(&fb_display[con].cmap, ivideo.video_cmap_len, 0);		if (err)			return err;	}#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)	if (con == info->currcon)		return fb_set_cmap(cmap, kspc, info);#else        if (con == currcon)		return fb_set_cmap(cmap, kspc, sisfb_setcolreg, info);#endif	else		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);	return 0;}#endif/* -------- functions only for 2.5 series ------- */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)static int sisfb_set_par(struct fb_info *info){	int err;	TWDEBUG("inside set_par\n");        if((err = sisfb_do_set_var(&info->var, 1, info)))		return err;	sisfb_get_fix(&info->fix, info->currcon, info);	TWDEBUG("end of set_par");	return 0;}static int sisfb_check_var(struct fb_var_screeninfo *var,                            struct fb_info *info){	unsigned int htotal =		var->left_margin + var->xres + var->right_margin +		var->hsync_len;	unsigned int vtotal = 0;	double drate = 0, hrate = 0;	int found_mode = 0;	int refresh_rate, search_idx;	TWDEBUG("Inside check_var");	if((var->vmode & FB_VMODE_MASK) == FB_VMODE_NONINTERLACED) {		vtotal = var->upper_margin + var->yres + var->lower_margin +		         var->vsync_len;   /* TW */		vtotal <<= 1;	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) {		vtotal = var->upper_margin + var->yres + var->lower_margin +		         var->vsync_len;   /* TW */		vtotal <<= 2;	} else if((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {		vtotal = var->upper_margin + (var->yres/2) + var->lower_margin +		         var->vsync_len;   /* TW */		/* var->yres <<= 1; */ /* TW */	} else 	vtotal = var->upper_margin + var->yres + var->lower_margin +		         var->vsync_len;	if(!(htotal) || !(vtotal)) {		SISFAIL("sisfb: no valid timing data");	}	drate = 1E12 / var->pixclock;	hrate = drate / htotal;	refresh_rate = (unsigned int) (hrate / vtotal * 2 + 0.5);	/* TW: Calculation wrong for 1024x600 - force it to 60Hz */	if((var->xres == 1024) && (var->yres == 600)) refresh_rate = 60;	search_idx = 0;	while( (sisbios_mode[search_idx].mode_no != 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)) {			found_mode = 1;			break;		}		search_idx++;	}	/* TW: TODO: Check the refresh rate */	if(found_mode)		search_idx = sisfb_validate_mode(search_idx);	else		SISFAIL("sisfb: no valid mode");       	if(sisfb_mode_idx < 0) {		SISFAIL("sisfb: mode not supported");	}	/* TW: Horiz-panning not supported */	if(var->xres != var->xres_virtual)		var->xres_virtual = var->xres;	if(!sisfb_ypan) {		if(var->yres != var->yres_virtual)			var->yres_virtual = var->yres;	} else {	   /* TW: Now patch yres_virtual if we use panning */	   /* *** May I do this? *** */	   var->yres_virtual = ivideo.heapstart / (var->xres * (var->bits_per_pixel >> 3));	    if(var->yres_virtual <= var->yres) {	    	/* TW: Paranoia check */	        var->yres_virtual = var->yres;	    }	}	TWDEBUG("end of check_var");	return 0;}#endif/* -------- functions for all series ------- */static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,			 struct fb_info *info){	TWDEBUG("inside get_fix");	memset(fix, 0, sizeof(struct fb_fix_screeninfo));	strcpy(fix->id, sis_fb_info.modename);	fix->smem_start = ivideo.video_base;        /* TW */        if((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {	    if (ivideo.video_size > 0x1000000) {	        fix->smem_len = 0xc00000;	    } else if (ivideo.video_size > 0x800000)		fix->smem_len = 0x800000;	    else		fix->smem_len = 0x400000;        } else		fix->smem_len = sisfb_mem * 1024;	fix->type        = video_type;	fix->type_aux    = 0;	if(ivideo.video_bpp == 8)		fix->visual = FB_VISUAL_PSEUDOCOLOR;	else		fix->visual = FB_VISUAL_TRUECOLOR;	fix->xpanstep    = 0;#ifdef SISFB_PAN        if(sisfb_ypan) 	 fix->ypanstep = 1;#endif	fix->ywrapstep   = 0;	fix->line_length = ivideo.video_linelength;	fix->mmio_start  = ivideo.mmio_base;	fix->mmio_len    = sisfb_mmio_size;	fix->accel       = FB_ACCEL_SIS_GLAMOUR;	fix->reserved[0] = ivideo.video_size & 0xFFFF;	fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF;	fix->reserved[2] = sisfb_caps;	TWDEBUG("end of get_fix");	return 0;}static int sisfb_get_var(struct fb_var_screeninfo *var, int con,			 struct fb_info *info){	TWDEBUG("inside get_var");	if(con == -1)		memcpy(var, &default_var, sizeof(struct fb_var_screeninfo));	else		*var = fb_display[con].var;	/* JennyLee 2001126: for FSTN */	if (var->xres == 320 && var->yres == 480)		var->yres = 240;	/* ~JennyLee */	TWDEBUG("end of get_var");	return 0;}#ifdef SISFB_PANstatic int sisfb_pan_display(struct fb_var_screeninfo *var, int con,		struct fb_info* info){#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#define currcon info->currcon#endif	TWDEBUG("inside pan_display");	if (var->vmode & FB_VMODE_YWRAP) {		if (var->yoffset < 0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset)			return -EINVAL;	} else {		if (var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual ||		    var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual)			return -EINVAL;	}        if (con == currcon)		sisfb_pan_var(var);	fb_display[con].var.xoffset = var->xoffset;	fb_display[con].var.yoffset = var->yoffset;	if (var->vmode & FB_VMODE_YWRAP)		fb_display[con].var.vmode |= FB_VMODE_YWRAP;	else		fb_display[con].var.vmode &= ~FB_VMODE_YWRAP;	TWDEBUG("end of pan_display");	return 0;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#undef currcon#endif}#endifstatic int sisfb_ioctl(struct inode *inode, struct file *file,		       unsigned int cmd, unsigned long arg, int con,		       struct fb_info *info){	TWDEBUG("inside ioctl");	switch (cmd) {	   case FBIO_ALLOC:		if (!capable(CAP_SYS_RAWIO))			return -EPERM;		sis_malloc((struct sis_memreq *) arg);		break;	   case FBIO_FREE:		if (!capable(CAP_SYS_RAWIO))			return -EPERM;		sis_free(*(unsigned long *) arg);		break;	   case FBIOGET_GLYPH:                sis_get_glyph(info,(SIS_GLYINFO *) arg);		break;	   case FBIOGET_HWCINFO:		{			unsigned long *hwc_offset = (unsigned long *) arg;			if (sisfb_caps & HW_CURSOR_CAP)				*hwc_offset = sisfb_hwcursor_vbase -				    (unsigned long) ivideo.video_vbase;			else				*hwc_offset = 0;			break;		}	   case FBIOPUT_MODEINFO:		{			struct mode_info *x = (struct mode_info *)arg;			ivideo.video_bpp        = x->bpp;			ivideo.video_width      = x->xres;			ivideo.video_height     = x->yres;			ivideo.video_vwidth     = x->v_xres;			ivideo.video_vheight    = x->v_yres;			ivideo.org_x            = x->org_x;			ivideo.org_y            = x->org_y;			ivideo.refresh_rate     = x->vrate;			ivideo.video_linelength = ivideo.video_width * (ivideo.video_bpp >> 3);			switch(ivideo.video_bpp) {        		case 8:            			ivideo.DstColor = 0x0000;	    			ivideo.SiS310_AccelDepth = 0x00000000;				ivideo.video_cmap_len = 256;            			break;        		case 16:            			ivideo.DstColor = 0x8000;            			ivideo.SiS310_AccelDepth = 0x00010000;				ivideo.video_cmap_len = 16;            			break;        		case 32:            			ivideo.DstColor = 0xC000;	    			ivideo.SiS310_AccelDepth = 0x00020000;				ivideo.video_cmap_len = 16;            			break;			default:				ivideo.video_cmap_len = 16;		       	 	printk(KERN_ERR "sisfb: Unsupported accel depth %d", ivideo.video_bpp);				break;    			}			break;		}	   case FBIOGET_DISPINFO:		sis_dispinfo((struct ap_data *)arg);		break;	   case SISFB_GET_INFO:  /* TW: New for communication with X driver */	        {			sisfb_info *x = (sisfb_info *)arg;			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;			x->fbvidmode = sisfb_mode_no;			x->sisfb_caps = sisfb_caps;			x->sisfb_tqlen = 512; /* yet unused */	                break;		}	   default:		return -EINVAL;	}	TWDEBUG("end of ioctl");	return 0;}static int sisfb_mmap(struct fb_info *info, struct file *file,		      struct vm_area_struct *vma){#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#define currcon info->currcon#endif	struct fb_var_screeninfo var;	unsigned long start;	unsigned long off;	u32 len;	TWDEBUG("inside mmap");	if(vma->vm_pgoff > (~0UL >> PAGE_SHIFT))  return -EINVAL;	off = vma->vm_pgoff << PAGE_SHIFT;	start = (unsigned long) ivideo.video_base;	len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size);	if (off >= len) {		off -= len;		sisfb_get_var(&var, currcon, info);		if(var.accel_flags) return -EINVAL;		start = (unsigned long) ivideo.mmio_base;		len = PAGE_ALIGN((start & ~PAGE_MASK) + sisfb_mmio_size);	}	start &= PAGE_MASK;	if((vma->vm_end - vma->vm_start + off) > len)	return -EINVAL;	off += start;	vma->vm_pgoff = off >> PAGE_SHIFT;#if defined(__i386__) || defined(__x86_64__)	if (boot_cpu_data.x86 > 3)		pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;#endif#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)	if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start,				vma->vm_page_prot))#else	/* TW: 2.5 API */	if (io_remap_page_range(vma, vma->vm_start, off, vma->vm_end - vma->vm_start,				vma->vm_page_prot))#endif		return -EAGAIN;        TWDEBUG("end of mmap");	return 0;#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)#undef currcon#endif}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)static struct fb_ops sisfb_ops = {	.owner        =	THIS_MODULE,	.fb_set_var   =	gen_set_var,	.fb_get_cmap  =	gen_get_cmap,	.fb_set_cmap  =	gen_set_cmap,	.fb_check_var = sisfb_check_var,	.fb_set_par   = sisfb_set_par,        .fb_setcolreg = sisfb_setcolreg,        .fb_blank     = sisfb_blank,#ifdef SISFB_PAN        .fb_pan_display = sisfb_pan_display,#endif        .fb_fillrect  = fbcon_sis_fillrect,	.fb_copyarea  = fbcon_sis_copyarea,	.fb_imageblit = my_cfb_imageblit,	.fb_ioctl     =	sisfb_ioctl,	.fb_mmap      =	sisfb_mmap,};#endif#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,33)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,#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,23)        fb_setcolreg:   sisfb_setcolreg,        fb_blank:       sisfb_blank,#endif

⌨️ 快捷键说明

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