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

📄 sis_main.c

📁 linux下的VIDEO接口驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	     } /*karl:endif (reg != 0xB1)*/	  	}}static void sisfb_crtc_to_var(struct fb_var_screeninfo *var){	u16 VRE, VBE, VRS, VBS, VDE, VT;	u16 HRE, HBE, HRS, HBS, HDE, HT;	u8  sr_data, cr_data, cr_data2, cr_data3, mr_data;	int A, B, C, D, E, F, temp;	double hrate, drate;	vgawb(SEQ_ADR, IND_SIS_COLOR_MODE);	sr_data = vgarb(SEQ_DATA);	if (sr_data & SIS_INTERLACED_MODE)		var->vmode = FB_VMODE_INTERLACED;	else		var->vmode = FB_VMODE_NONINTERLACED;	switch ((sr_data & 0x1C) >> 2) {	   case SIS_8BPP_COLOR_MODE:		var->bits_per_pixel = 8;		break;	   case SIS_16BPP_COLOR_MODE:		var->bits_per_pixel = 16;		break;	   case SIS_32BPP_COLOR_MODE:		var->bits_per_pixel = 32;		break;	}	switch (var->bits_per_pixel) {	   case 8:		var->red.length = 6;		var->green.length = 6;		var->blue.length = 6;		video_cmap_len = 256;		break;	   case 16:		var->red.offset = 11;		var->red.length = 5;		var->green.offset = 5;		var->green.length = 6;		var->blue.offset = 0;		var->blue.length = 5;		var->transp.offset = 0;		var->transp.length = 0;		video_cmap_len = 16;		break;	   case 24:		var->red.offset = 16;		var->red.length = 8;		var->green.offset = 8;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		var->transp.offset = 0;		var->transp.length = 0;		video_cmap_len = 16;		break;	   case 32:		var->red.offset = 16;		var->red.length = 8;		var->green.offset = 8;		var->green.length = 8;		var->blue.offset = 0;		var->blue.length = 8;		var->transp.offset = 24;		var->transp.length = 8;		video_cmap_len = 16;		break;	}	vgawb(SEQ_ADR, 0xA);	sr_data = vgarb(SEQ_DATA);	vgawb(CRTC_ADR, 0x6);	cr_data = vgarb(CRTC_DATA);	vgawb(CRTC_ADR, 0x7);	cr_data2 = vgarb(CRTC_DATA);	VT = (cr_data & 0xFF) | ((u16) (cr_data2 & 0x01) << 8) |	     ((u16) (cr_data2 & 0x20) << 4) | ((u16) (sr_data & 0x01) <<					      10);	A = VT + 2;	vgawb(CRTC_ADR, 0x12);	cr_data = vgarb(CRTC_DATA);	VDE = (cr_data & 0xff) | ((u16) (cr_data2 & 0x02) << 7) |	      ((u16) (cr_data2 & 0x40) << 3) | ((u16) (sr_data & 0x02) << 9);	E = VDE + 1;	vgawb(CRTC_ADR, 0x10);	cr_data = vgarb(CRTC_DATA);	VRS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x04) << 6) |	      ((u16) (cr_data2 & 0x80) << 2) | ((u16) (sr_data & 0x08) << 7);	F = VRS + 1 - E;	vgawb(CRTC_ADR, 0x15);	cr_data = vgarb(CRTC_DATA);	vgawb(CRTC_ADR, 0x9);	cr_data3 = vgarb(CRTC_DATA);	VBS = (cr_data & 0xff) | ((u16) (cr_data2 & 0x08) << 5) |	      ((u16) (cr_data3 & 0x20) << 4) | ((u16) (sr_data & 0x04) << 8);	vgawb(CRTC_ADR, 0x16);	cr_data = vgarb(CRTC_DATA);	VBE = (cr_data & 0xff) | ((u16) (sr_data & 0x10) << 4);	temp = VBE - ((E - 1) & 511);	B = (temp > 0) ? temp : (temp + 512);	vgawb(CRTC_ADR, 0x11);	cr_data = vgarb(CRTC_DATA);	VRE = (cr_data & 0x0f) | ((sr_data & 0x20) >> 1);	temp = VRE - ((E + F - 1) & 31);	C = (temp > 0) ? temp : (temp + 32);	D = B - F - C;	var->yres = var->yres_virtual = E;	/* TW: We have to report the physical dimension to the console! */	if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {		var->yres <<= 1;		var->yres_virtual <<=1;	}	/* TW end */	var->upper_margin = D;	var->lower_margin = F;	var->vsync_len = C;	vgawb(SEQ_ADR, 0xb);	sr_data = vgarb(SEQ_DATA);	vgawb(CRTC_ADR, 0x0);	cr_data = vgarb(CRTC_DATA);	HT = (cr_data & 0xff) | ((u16) (sr_data & 0x03) << 8);	A = HT + 5;	vgawb(CRTC_ADR, 0x1);	cr_data = vgarb(CRTC_DATA);	HDE = (cr_data & 0xff) | ((u16) (sr_data & 0x0C) << 6);	E = HDE + 1;	vgawb(CRTC_ADR, 0x4);	cr_data = vgarb(CRTC_DATA);	HRS = (cr_data & 0xff) | ((u16) (sr_data & 0xC0) << 2);	F = HRS - E - 3;	vgawb(CRTC_ADR, 0x2);	cr_data = vgarb(CRTC_DATA);	HBS = (cr_data & 0xff) | ((u16) (sr_data & 0x30) << 4);	vgawb(SEQ_ADR, 0xc);	sr_data = vgarb(SEQ_DATA);	vgawb(CRTC_ADR, 0x3);	cr_data = vgarb(CRTC_DATA);	vgawb(CRTC_ADR, 0x5);	cr_data2 = vgarb(CRTC_DATA);	HBE = (cr_data & 0x1f) | ((u16) (cr_data2 & 0x80) >> 2) |	      ((u16) (sr_data & 0x03) << 6);	HRE = (cr_data2 & 0x1f) | ((sr_data & 0x04) << 3);	temp = HBE - ((E - 1) & 255);	B = (temp > 0) ? temp : (temp + 256);	temp = HRE - ((E + F + 3) & 63);	C = (temp > 0) ? temp : (temp + 64);	D = B - F - C;	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 = vgarb(0x1C);	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);}/* ------------------ Public Routines -------------------------------- */static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con,			 struct fb_info *info){	memset(fix, 0, sizeof(struct fb_fix_screeninfo));	strcpy(fix->id, fb_info.modename);	fix->smem_start = ivideo.video_base;                /*karl:10/01/2001*/ /* TW */        if ((!sisfb_mem) || (sisfb_mem > (ivideo.video_size/1024))) {	    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;	fix->ypanstep = 0;	fix->ywrapstep = 0;	fix->line_length = 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;		return 0;}static int sisfb_get_var(struct fb_var_screeninfo *var, int con,			 struct fb_info *info){	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 */	return 0;}static int sisfb_set_var(struct fb_var_screeninfo *var, int con,			 struct fb_info *info){	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);	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;}static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,			  struct fb_info *info){	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(video_cmap_len), cmap, kspc ? 0 : 2);	return 0;}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, video_cmap_len, 0);		if (err)			return err;	}	if (con == currcon)			return fb_set_cmap(cmap, kspc, sis_setcolreg, info);	else		fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);	return 0;}static int sisfb_ioctl(struct inode *inode, struct file *file,		       unsigned int cmd, unsigned long arg, int con,		       struct fb_info *info){	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((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;						break;		}	   case FBIOGET_DISPINFO:		sis_dispinfo((struct ap_data *)arg);		break;	   default:		return -EINVAL;	}	return 0;}static int sisfb_mmap(struct fb_info *info, struct file *file,		      struct vm_area_struct *vma){	struct fb_var_screeninfo var;	unsigned long start;	unsigned long off;	u32 len;	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__)	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;	return 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_ioctl:	sisfb_ioctl,	fb_mmap:	sisfb_mmap,};/* ------------ Interface to the low level console driver -------------*/static int sisfb_update_var(int con, struct fb_info *info){	return 0;}static int sisfb_switch(int con, struct fb_info *info){	int cols, rows;	if (fb_display[currcon].cmap.len)		fb_get_cmap(&fb_display[currcon].cmap, 1, sis_getcolreg, info);	fb_display[con].var.activate = FB_ACTIVATE_NOW;	if (!memcmp(&fb_display[con].var, &fb_display[currcon].var,	                           sizeof(struct fb_var_screeninfo))) {		currcon = con;		return 1;	}	currcon = con;	sisfb_do_set_var(&fb_display[con].var, 1, info);	sisfb_set_disp(con, &fb_display[con].var);		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);	sisfb_update_var(con, info);	return 1;}static void sisfb_blank(int blank, struct fb_info *info){	u8 reg;	vgawb(CRTC_ADR, 0x17);	reg = vgarb(CRTC_DATA);	if (blank > 0)				reg &= 0x7f;	else					reg |= 0x80;	vgawb(CRTC_ADR, 0x17);	vgawb(CRTC_DATA, reg);}int sisfb_setup(char *options){	char *this_opt;	fb_info.fontname[0] = '\0';	ivideo.refresh_rate = 0;	if (!options || !*options)		return 0;#if 0	/* TW (Alex Tribble): Change for 2.5 series */	for (this_opt = strtok(options, ","); this_opt;	     this_opt = strtok(NULL, ",")) {#endif	while((this_opt = strsep(&options, ","))) {		if (!*this_opt)			continue;		if (!strcmp(this_opt, "inverse")) {			sisfb_inverse = 1;			fb_invert_cmaps();		} else if (!strncmp(this_opt, "font:", 5)) {			strcpy(fb_info.fontname, this_opt + 5);		} else if (!strncmp(this_opt, "mode:", 5)) {			sisfb_search_mode(this_opt + 5);		} else if (!strncmp(this_opt, "vrate:", 6)) {			ivideo.refresh_rate =			    simple_strtoul(this_opt + 6, NULL, 0);		} else if (!strncmp(this_opt, "rate:", 5)) {			ivideo.refresh_rate =			    simple_strtoul(this_opt + 5, NULL, 0);		} else if (!strncmp(this_opt, "off", 3)) {			sisfb_off = 1;		} else if (!strncmp(this_opt, "crt1off", 7)) {			sisfb_crt1off = 1;		} else if (!strncmp(this_opt, "filter:", 7)) {			filter = (int)simple_strtoul(this_opt + 7, NULL, 0);		

⌨️ 快捷键说明

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