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

📄 sisusb_con.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (sisusb_is_inactive(c, sisusb) || sisusb->con_blanked) {		up(&sisusb->lock);		return 0;	}	c->vc_origin = c->vc_visible_origin = sisusb->scrbuf;	sisusbcon_set_start_address(sisusb, c);	sisusb->con_rolled_over = 0;	up(&sisusb->lock);	return 1;}/* Interface routine */static intsisusbcon_resize(struct vc_data *c, unsigned int newcols, unsigned int newrows){	struct sisusb_usb_data *sisusb;	int fh;	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))		return -ENODEV;	fh = sisusb->current_font_height;	up(&sisusb->lock);	/* We are quite unflexible as regards resizing. The vt code	 * handles sizes where the line length isn't equal the pitch	 * quite badly. As regards the rows, our panning tricks only	 * work well if the number of rows equals the visible number	 * of rows.	 */	if (newcols != 80 || c->vc_scan_lines / fh != newrows)		return -EINVAL;	return 0;}intsisusbcon_do_font_op(struct sisusb_usb_data *sisusb, int set, int slot,			u8 *arg, int cmapsz, int ch512, int dorecalc,			struct vc_data *c, int fh, int uplock){	int font_select = 0x00, i, err = 0;	u32 offset = 0;	u8 dummy;	/* sisusb->lock is down */	/*	 * The default font is kept in slot 0.	 * A user font is loaded in slot 2 (256 ch)	 * or 2+3 (512 ch).	 */	if ((slot != 0 && slot != 2) || !fh) {		if (uplock)			up(&sisusb->lock);		return -EINVAL;	}	if (set)		sisusb->font_slot = slot;	/* Default font is always 256 */	if (slot == 0)		ch512 = 0;	else		offset = 4 * cmapsz;	font_select = (slot == 0) ? 0x00 : (ch512 ? 0x0e : 0x0a);	err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */	err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x04); /* Write to plane 2 */	err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x07); /* Memory mode a0-bf */	err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset */	if (err)		goto font_op_error;	err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x03); /* Select plane read 2 */	err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x00); /* Disable odd/even */	err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x00); /* Address range a0-bf */	if (err)		goto font_op_error;	if (arg) {		if (set)			for (i = 0; i < cmapsz; i++) {				err |= sisusb_writeb(sisusb,					sisusb->vrambase + offset + i,					arg[i]);				if (err)					break;			}		else			for (i = 0; i < cmapsz; i++) {				err |= sisusb_readb(sisusb,					sisusb->vrambase + offset + i,					&arg[i]);				if (err)					break;			}		/*		 * In 512-character mode, the character map is not contiguous if		 * we want to remain EGA compatible -- which we do		 */		if (ch512) {			if (set)				for (i = 0; i < cmapsz; i++) {					err |= sisusb_writeb(sisusb,						sisusb->vrambase + offset +							(2 * cmapsz) + i,						arg[cmapsz + i]);					if (err)						break;				}			else				for (i = 0; i < cmapsz; i++) {					err |= sisusb_readb(sisusb,						sisusb->vrambase + offset +							(2 * cmapsz) + i,						&arg[cmapsz + i]);					if (err)						break;				}		}	}	if (err)		goto font_op_error;	err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x01); /* Reset */	err |= sisusb_setidxreg(sisusb, SISSR, 0x02, 0x03); /* Write to planes 0+1 */	err |= sisusb_setidxreg(sisusb, SISSR, 0x04, 0x03); /* Memory mode a0-bf */	if (set)		sisusb_setidxreg(sisusb, SISSR, 0x03, font_select);	err |= sisusb_setidxreg(sisusb, SISSR, 0x00, 0x03); /* Reset end */	if (err)		goto font_op_error;	err |= sisusb_setidxreg(sisusb, SISGR, 0x04, 0x00); /* Select plane read 0 */	err |= sisusb_setidxreg(sisusb, SISGR, 0x05, 0x10); /* Enable odd/even */	err |= sisusb_setidxreg(sisusb, SISGR, 0x06, 0x06); /* Address range b8-bf */	if (err)		goto font_op_error;	if ((set) && (ch512 != sisusb->current_font_512)) {		/* Font is shared among all our consoles.		 * And so is the hi_font_mask.		 */		for (i = 0; i < MAX_NR_CONSOLES; i++) {			struct vc_data *c = vc_cons[i].d;			if (c && c->vc_sw == &sisusb_con)				c->vc_hi_font_mask = ch512 ? 0x0800 : 0;		}		sisusb->current_font_512 = ch512;		/* color plane enable register:			256-char: enable intensity bit			512-char: disable intensity bit */		sisusb_getreg(sisusb, SISINPSTAT, &dummy);		sisusb_setreg(sisusb, SISAR, 0x12);		sisusb_setreg(sisusb, SISAR, ch512 ? 0x07 : 0x0f);		sisusb_getreg(sisusb, SISINPSTAT, &dummy);		sisusb_setreg(sisusb, SISAR, 0x20);		sisusb_getreg(sisusb, SISINPSTAT, &dummy);	}	if (dorecalc) {		/*		 * Adjust the screen to fit a font of a certain height		 */		unsigned char ovr, vde, fsr;		int rows = 0, maxscan = 0;		if (c) {			/* Number of video rows */			rows = c->vc_scan_lines / fh;			/* Scan lines to actually display-1 */			maxscan = rows * fh - 1;			/*printk(KERN_DEBUG "sisusb recalc rows %d maxscan %d fh %d sl %d\n",				rows, maxscan, fh, c->vc_scan_lines);*/			sisusb_getidxreg(sisusb, SISCR, 0x07, &ovr);			vde = maxscan & 0xff;			ovr = (ovr & 0xbd) |			      ((maxscan & 0x100) >> 7) |			      ((maxscan & 0x200) >> 3);			sisusb_setidxreg(sisusb, SISCR, 0x07, ovr);			sisusb_setidxreg(sisusb, SISCR, 0x12, vde);		}		sisusb_getidxreg(sisusb, SISCR, 0x09, &fsr);		fsr = (fsr & 0xe0) | (fh - 1);		sisusb_setidxreg(sisusb, SISCR, 0x09, fsr);		sisusb->current_font_height = fh;		sisusb->sisusb_cursor_size_from = -1;		sisusb->sisusb_cursor_size_to   = -1;	}	if (uplock)		up(&sisusb->lock);	if (dorecalc && c) {		int i, rows = c->vc_scan_lines / fh;		/* Now adjust our consoles' size */		for (i = 0; i < MAX_NR_CONSOLES; i++) {			struct vc_data *vc = vc_cons[i].d;			if (vc && vc->vc_sw == &sisusb_con) {				if (CON_IS_VISIBLE(vc)) {					vc->vc_sw->con_cursor(vc, CM_DRAW);				}				vc->vc_font.height = fh;				vc_resize(vc, 0, rows);			}		}	}	return 0;font_op_error:	if (uplock)		up(&sisusb->lock);	return -EIO;}/* Interface routine */static intsisusbcon_font_set(struct vc_data *c, struct console_font *font,							unsigned flags){	struct sisusb_usb_data *sisusb;	unsigned charcount = font->charcount;	if (font->width != 8 || (charcount != 256 && charcount != 512))		return -EINVAL;	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))		return -ENODEV;	/* sisusb->lock is down */	/* Save the user-provided font into a buffer. This	 * is used for restoring text mode after quitting	 * from X and for the con_getfont routine.	 */	if (sisusb->font_backup) {		if (sisusb->font_backup_size < charcount) {			vfree(sisusb->font_backup);			sisusb->font_backup = NULL;		}	}	if (!sisusb->font_backup)		sisusb->font_backup = vmalloc(charcount * 32);	if (sisusb->font_backup) {		memcpy(sisusb->font_backup, font->data, charcount * 32);		sisusb->font_backup_size = charcount;		sisusb->font_backup_height = font->height;		sisusb->font_backup_512 = (charcount == 512) ? 1 : 0;	}	/* do_font_op ups sisusb->lock */	return sisusbcon_do_font_op(sisusb, 1, 2, font->data,			8192, (charcount == 512),			(!(flags & KD_FONT_FLAG_DONT_RECALC)) ? 1 : 0,			c, font->height, 1);}/* Interface routine */static intsisusbcon_font_get(struct vc_data *c, struct console_font *font){	struct sisusb_usb_data *sisusb;	if (!(sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num)))		return -ENODEV;	/* sisusb->lock is down */	font->width = 8;	font->height = c->vc_font.height;	font->charcount = 256;	if (!font->data) {		up(&sisusb->lock);		return 0;	}	if (!sisusb->font_backup) {		up(&sisusb->lock);		return -ENODEV;	}	/* Copy 256 chars only, like vgacon */	memcpy(font->data, sisusb->font_backup, 256 * 32);	up(&sisusb->lock);	return 0;}/* *  The console `switch' structure for the sisusb console */static const struct consw sisusb_con = {	.owner =		THIS_MODULE,	.con_startup =		sisusbcon_startup,	.con_init =		sisusbcon_init,	.con_deinit =		sisusbcon_deinit,	.con_clear =		sisusbcon_clear,	.con_putc =		sisusbcon_putc,	.con_putcs =		sisusbcon_putcs,	.con_cursor =		sisusbcon_cursor,	.con_scroll =		sisusbcon_scroll,	.con_bmove =		sisusbcon_bmove,	.con_switch =		sisusbcon_switch,	.con_blank =		sisusbcon_blank,	.con_font_set =		sisusbcon_font_set,	.con_font_get =		sisusbcon_font_get,	.con_set_palette =	sisusbcon_set_palette,	.con_scrolldelta =	sisusbcon_scrolldelta,	.con_build_attr =	sisusbcon_build_attr,	.con_invert_region =	sisusbcon_invert_region,	.con_set_origin =	sisusbcon_set_origin,	.con_save_screen =	sisusbcon_save_screen,	.con_resize =		sisusbcon_resize,};/* Our very own dummy console driver */static const char *sisusbdummycon_startup(void){    return "SISUSBVGADUMMY";}static void sisusbdummycon_init(struct vc_data *vc, int init){    vc->vc_can_do_color = 1;    if (init) {	vc->vc_cols = 80;	vc->vc_rows = 25;    } else	vc_resize(vc, 80, 25);}static int sisusbdummycon_dummy(void){    return 0;}#define SISUSBCONDUMMY	(void *)sisusbdummycon_dummyconst struct consw sisusb_dummy_con = {	.owner =		THIS_MODULE,	.con_startup =		sisusbdummycon_startup,	.con_init =		sisusbdummycon_init,	.con_deinit =		SISUSBCONDUMMY,	.con_clear =		SISUSBCONDUMMY,	.con_putc =		SISUSBCONDUMMY,	.con_putcs =		SISUSBCONDUMMY,	.con_cursor =		SISUSBCONDUMMY,	.con_scroll =		SISUSBCONDUMMY,	.con_bmove =		SISUSBCONDUMMY,	.con_switch =		SISUSBCONDUMMY,	.con_blank =		SISUSBCONDUMMY,	.con_font_set =		SISUSBCONDUMMY,	.con_font_get =		SISUSBCONDUMMY,	.con_font_default =	SISUSBCONDUMMY,	.con_font_copy =	SISUSBCONDUMMY,	.con_set_palette =	SISUSBCONDUMMY,	.con_scrolldelta =	SISUSBCONDUMMY,};intsisusb_console_init(struct sisusb_usb_data *sisusb, int first, int last){	int i, ret, minor = sisusb->minor;	down(&disconnect_sem);	down(&sisusb->lock);	/* Erm.. that should not happen */	if (sisusb->haveconsole || !sisusb->SiS_Pr) {		up(&sisusb->lock);		up(&disconnect_sem);		return 1;	}	sisusb->con_first = first;	sisusb->con_last  = last;	if (first > last ||	    first > MAX_NR_CONSOLES ||	    last > MAX_NR_CONSOLES) {		up(&sisusb->lock);		up(&disconnect_sem);		return 1;	}	/* If gfxcore not initialized or no consoles given, quit graciously */	if (!sisusb->gfxinit || first < 1 || last < 1) {		up(&sisusb->lock);		up(&disconnect_sem);		return 0;	}	sisusb->sisusb_cursor_loc       = -1;	sisusb->sisusb_cursor_size_from = -1;	sisusb->sisusb_cursor_size_to   = -1;	/* Set up text mode (and upload  default font) */	if (sisusb_reset_text_mode(sisusb, 1)) {		up(&sisusb->lock);		up(&disconnect_sem);		printk(KERN_ERR			"sisusbvga[%d]: Failed to set up text mode\n",			minor);		return 1;	}	/* Initialize some gfx registers */	sisusb_initialize(sisusb);	for (i = first - 1; i <= last - 1; i++) {		/* Save sisusb for our interface routines */		mysisusbs[i] = sisusb;	}	/* Initial console setup */	sisusb->sisusb_num_columns = 80;	/* Use a 32K buffer (matches b8000-bffff area) */	sisusb->scrbuf_size = 32 * 1024;	/* Allocate screen buffer */	if (!(sisusb->scrbuf = (unsigned long)vmalloc(sisusb->scrbuf_size))) {		up(&sisusb->lock);		up(&disconnect_sem);		printk(KERN_ERR			"sisusbvga[%d]: Failed to allocate screen buffer\n",			minor);		return 1;	}	up(&sisusb->lock);	up(&disconnect_sem);	/* Now grab the desired console(s) */	ret = take_over_console(&sisusb_con, first - 1, last - 1, 0);	if (!ret)		sisusb->haveconsole = 1;	else {		for (i = first - 1; i <= last - 1; i++)			mysisusbs[i] = NULL;	}	return ret;}voidsisusb_console_exit(struct sisusb_usb_data *sisusb){	int i;	/* This is called if the device is disconnected	 * and while disconnect and lock semaphores	 * are up. This should be save because we	 * can't lose our sisusb any other way but by	 * disconnection (and hence, the disconnect	 * sema is for protecting all other access	 * functions from disconnection, not the	 * other way round).	 */	/* Now what do we do in case of disconnection:	 * One alternative would be to simply call	 * give_up_console(). Nah, not a good idea.	 * give_up_console() is obviously buggy as it	 * only discards the consw pointer from the	 * driver_map, but doesn't adapt vc->vc_sw	 * of the affected consoles. Hence, the next	 * call to any of the console functions will	 * eventually take a trip to oops county.	 * Also, give_up_console for some reason	 * doesn't decrement our module refcount.	 * Instead, we switch our consoles to a private	 * dummy console. This, of course, keeps our	 * refcount up as well, but it works perfectly.	 */	if (sisusb->haveconsole) {		for (i = 0; i < MAX_NR_CONSOLES; i++)			if (sisusb->havethisconsole[i])				take_over_console(&sisusb_dummy_con, i, i, 0);				/* At this point, con_deinit for all our				 * consoles is executed by take_over_console().				 */		sisusb->haveconsole = 0;	}	vfree((void *)sisusb->scrbuf);	sisusb->scrbuf = 0;	vfree(sisusb->font_backup);	sisusb->font_backup = NULL;}void __init sisusb_init_concode(void){	int i;	for (i = 0; i < MAX_NR_CONSOLES; i++)		mysisusbs[i] = NULL;}#endif /* INCL_CON */

⌨️ 快捷键说明

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