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

📄 tty3270.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
 */static voidtty3270_issue_read(struct tty3270 *tp, int lock){	struct raw3270_request *rrq;	int rc;	rrq = xchg(&tp->read, 0);	if (!rrq)		/* Read already scheduled. */		return;	rrq->callback = tty3270_read_callback;	rrq->callback_data = tp;	raw3270_request_set_cmd(rrq, TC_READMOD);	raw3270_request_set_data(rrq, tp->input->string, tp->input->len);	/* Issue the read modified request. */	if (lock) {		rc = raw3270_start(&tp->view, rrq);	} else		rc = raw3270_start_irq(&tp->view, rrq);	if (rc) {		raw3270_request_reset(rrq);		xchg(&tp->read, rrq);	}}/* * Switch to the tty view. */static inttty3270_activate(struct raw3270_view *view){	struct tty3270 *tp;	unsigned long flags;	tp = (struct tty3270 *) view;	spin_lock_irqsave(&tp->view.lock, flags);	tp->nr_up = 0;	tty3270_rebuild_update(tp);	tty3270_update_status(tp);	tp->update_flags = TTY_UPDATE_ALL;	tty3270_set_timer(tp, 1);	spin_unlock_irqrestore(&tp->view.lock, flags);	return 0;}static voidtty3270_deactivate(struct raw3270_view *view){}static inttty3270_irq(struct tty3270 *tp, struct raw3270_request *rq, struct irb *irb){	/* Handle ATTN. Schedule tasklet to read aid. */	if (irb->scsw.dstat & DEV_STAT_ATTENTION) {		if (!tp->throttle)			tty3270_issue_read(tp, 0);		else			tp->attn = 1;	}	if (rq) {		if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK)			rq->rc = -EIO;		else			/* Normal end. Copy residual count. */			rq->rescnt = irb->scsw.count;	}	return RAW3270_IO_DONE;}/* * Allocate tty3270 structure. */static struct tty3270 *tty3270_alloc_view(void){	struct tty3270 *tp;	int pages;	tp = kmalloc(sizeof(struct tty3270),GFP_KERNEL);	if (!tp)		goto out_err;	memset(tp, 0, sizeof(struct tty3270));	tp->freemem_pages =		kmalloc(sizeof(void *) * TTY3270_STRING_PAGES, GFP_KERNEL);	if (!tp->freemem_pages)		goto out_tp;	INIT_LIST_HEAD(&tp->freemem);	init_timer(&tp->timer);	for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) {		tp->freemem_pages[pages] = (void *)			__get_free_pages(GFP_KERNEL|GFP_DMA, 0);		if (!tp->freemem_pages[pages])			goto out_pages;		add_string_memory(&tp->freemem,				  tp->freemem_pages[pages], PAGE_SIZE);	}	tp->write = raw3270_request_alloc(TTY3270_OUTPUT_BUFFER_SIZE);	if (IS_ERR(tp->write))		goto out_pages;	tp->read = raw3270_request_alloc(0);	if (IS_ERR(tp->read))		goto out_write;	tp->kreset = raw3270_request_alloc(1);	if (IS_ERR(tp->kreset))		goto out_read;	tp->kbd = kbd_alloc();	if (!tp->kbd)		goto out_reset;	return tp;out_reset:	raw3270_request_free(tp->kreset);out_read:	raw3270_request_free(tp->read);out_write:	raw3270_request_free(tp->write);out_pages:	while (pages--)		free_pages((unsigned long) tp->freemem_pages[pages], 0);	kfree(tp->freemem_pages);out_tp:	kfree(tp);out_err:	return ERR_PTR(-ENOMEM);}/* * Free tty3270 structure. */static voidtty3270_free_view(struct tty3270 *tp){	int pages;	kbd_free(tp->kbd);	raw3270_request_free(tp->kreset);	raw3270_request_free(tp->read);	raw3270_request_free(tp->write);	for (pages = 0; pages < TTY3270_STRING_PAGES; pages++)		free_pages((unsigned long) tp->freemem_pages[pages], 0);	kfree(tp->freemem_pages);	kfree(tp);}/* * Allocate tty3270 screen. */static inttty3270_alloc_screen(struct tty3270 *tp){	unsigned long size;	int lines;	size = sizeof(struct tty3270_line) * (tp->view.rows - 2);	tp->screen = kmalloc(size, GFP_KERNEL);	if (!tp->screen)		goto out_err;	memset(tp->screen, 0, size);	for (lines = 0; lines < tp->view.rows - 2; lines++) {		size = sizeof(struct tty3270_cell) * tp->view.cols;		tp->screen[lines].cells = kmalloc(size, GFP_KERNEL);		if (!tp->screen[lines].cells)			goto out_screen;		memset(tp->screen[lines].cells, 0, size);	}	return 0;out_screen:	while (lines--)		kfree(tp->screen[lines].cells);	kfree(tp->screen);out_err:	return -ENOMEM;}/* * Free tty3270 screen. */static voidtty3270_free_screen(struct tty3270 *tp){	int lines;	for (lines = 0; lines < tp->view.rows - 2; lines++)		kfree(tp->screen[lines].cells);	kfree(tp->screen);}/* * Unlink tty3270 data structure from tty. */static voidtty3270_release(struct raw3270_view *view){	struct tty3270 *tp;	struct tty_struct *tty;	tp = (struct tty3270 *) view;	tty = tp->tty;	if (tty) {		tty->driver_data = 0;		tp->tty = tp->kbd->tty = 0;		tty_hangup(tty);		raw3270_put_view(&tp->view);	}}/* * Free tty3270 data structure */static voidtty3270_free(struct raw3270_view *view){	tty3270_free_screen((struct tty3270 *) view);	tty3270_free_view((struct tty3270 *) view);}/* * Delayed freeing of tty3270 views. */static voidtty3270_del_views(void){	struct tty3270 *tp;	int i;	for (i = 0; i < tty3270_max_index; i++) {		tp = (struct tty3270 *)			raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR);		if (!IS_ERR(tp))			raw3270_del_view(&tp->view);	}}struct raw3270_fn tty3270_fn = {	.activate = tty3270_activate,	.deactivate = tty3270_deactivate,	.intv = (void *) tty3270_irq,	.release = tty3270_release,	.free = tty3270_free};/* * This routine is called whenever a 3270 tty is opened. */static inttty3270_open(struct tty_struct *tty, struct file * filp){	struct tty3270 *tp;	int i, rc;	if (tty->count > 1)		return 0;	/* Check if the tty3270 is already there. */	tp = (struct tty3270 *)		raw3270_find_view(&tty3270_fn,				  tty->index + RAW3270_FIRSTMINOR);	if (!IS_ERR(tp)) {		tty->driver_data = tp;		tty->winsize.ws_row = tp->view.rows - 2;		tty->winsize.ws_col = tp->view.cols;		tty->low_latency = 0;		tp->tty = tty;		tp->kbd->tty = tty;		tp->inattr = TF_INPUT;		return 0;	}	if (tty3270_max_index < tty->index + 1)		tty3270_max_index = tty->index + 1;	/* Quick exit if there is no device for tty->index. */	if (PTR_ERR(tp) == -ENODEV)		return -ENODEV;	/* Allocate tty3270 structure on first open. */	tp = tty3270_alloc_view();	if (IS_ERR(tp))		return PTR_ERR(tp);	INIT_LIST_HEAD(&tp->lines);	INIT_LIST_HEAD(&tp->update);	INIT_LIST_HEAD(&tp->rcl_lines);	tp->rcl_max = 20;	init_timer(&tp->timer);	tasklet_init(&tp->readlet, 		     (void (*)(unsigned long)) tty3270_read_tasklet,		     (unsigned long) tp->read);	rc = raw3270_add_view(&tp->view, &tty3270_fn,			      tty->index + RAW3270_FIRSTMINOR);	if (rc) {		tty3270_free_view(tp);		return rc;	}	rc = tty3270_alloc_screen(tp);	if (rc) {		raw3270_put_view(&tp->view);		raw3270_del_view(&tp->view);		return rc;	}	tp->tty = tty;	tty->low_latency = 0;	tty->driver_data = tp;	tty->winsize.ws_row = tp->view.rows - 2;	tty->winsize.ws_col = tp->view.cols;	tty3270_create_prompt(tp);	tty3270_create_status(tp);	tty3270_update_status(tp);	/* Create blank line for every line in the tty output area. */	for (i = 0; i < tp->view.rows - 2; i++)		tty3270_blank_line(tp);	tp->kbd->tty = tty;	tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty;	tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward;	tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward;	tp->kbd->fn_handler[KVAL(K_CONS)] = tty3270_rcl_backward;	kbd_ascebc(tp->kbd, tp->view.ascebc);	raw3270_activate_view(&tp->view);	return 0;}/* * This routine is called when the 3270 tty is closed. We wait * for the remaining request to be completed. Then we clean up. */static voidtty3270_close(struct tty_struct *tty, struct file * filp){	struct tty3270 *tp;	if (tty->count > 1)		return;	tp = (struct tty3270 *) tty->driver_data;	if (tp) {		tty->driver_data = 0;		tp->tty = tp->kbd->tty = 0;		raw3270_put_view(&tp->view);	}}/* * We always have room. */static inttty3270_write_room(struct tty_struct *tty){	return INT_MAX;}/* * Insert character into the screen at the current position with the * current color and highlight. This function does NOT do cursor movement. */static voidtty3270_put_character(struct tty3270 *tp, char ch){	struct tty3270_line *line;	struct tty3270_cell *cell;	line = tp->screen + tp->cy;	if (line->len <= tp->cx) {		while (line->len < tp->cx) {			cell = line->cells + line->len;			cell->character = tp->view.ascebc[' '];			cell->highlight = tp->highlight;			cell->f_color = tp->f_color;			line->len++;		}		line->len++;	}	cell = line->cells + tp->cx;	cell->character = tp->view.ascebc[(unsigned int) ch];	cell->highlight = tp->highlight;	cell->f_color = tp->f_color;}/* * Convert a tty3270_line to a 3270 data fragment usable for output. */static voidtty3270_convert_line(struct tty3270 *tp, int line_nr){	struct tty3270_line *line;	struct tty3270_cell *cell;	struct string *s, *n;	unsigned char highlight;	unsigned char f_color;	char *cp;	int flen, i;	/* Determine how long the fragment will be. */	flen = 3;		/* Prefix (TO_SBA). */	line = tp->screen + line_nr;	flen += line->len;	highlight = TAX_RESET;	f_color = TAC_RESET;	for (i = 0, cell = line->cells; i < line->len; i++, cell++) {		if (cell->highlight != highlight) {			flen += 3;	/* TO_SA to switch highlight. */			highlight = cell->highlight;		}		if (cell->f_color != f_color) {			flen += 3;	/* TO_SA to switch color. */			f_color = cell->f_color;		}	}	if (highlight != TAX_RESET)		flen += 3;	/* TO_SA to reset hightlight. */	if (f_color != TAC_RESET)		flen += 3;	/* TO_SA to reset color. */	if (line->len < tp->view.cols)		flen += 4;	/* Postfix (TO_RA). */	/* Find the line in the list. */	i = tp->view.rows - 2 - line_nr;	list_for_each_entry_reverse(s, &tp->lines, list)		if (--i <= 0)			break;	/*	 * Check if the line needs to get reallocated.	 */	if (s->len != flen) {		/* Reallocate string. */		n = tty3270_alloc_string(tp, flen);		list_add(&n->list, &s->list);		list_del_init(&s->list);		if (!list_empty(&s->update))			list_del_init(&s->update);		free_string(&tp->freemem, s);		s = n;	}	/* Write 3270 data fragment. */	cp = s->string;	*cp++ = TO_SBA;	*cp++ = 0;	*cp++ = 0;	highlight = TAX_RESET;	f_color = TAC_RESET;	for (i = 0, cell = line->cells; i < line->len; i++, cell++) {		if (cell->highlight != highlight) {			*cp++ = TO_SA;			*cp++ = TAT_EXTHI;			*cp++ = cell->highlight;			highlight = cell->highlight;		}		if (cell->f_color != f_color) {			*cp++ = TO_SA;			*cp++ = TAT_COLOR;			*cp++ = cell->f_color;			f_color = cell->f_color;		}		*cp++ = cell->character;	}	if (highlight != TAX_RESET) {		*cp++ = TO_SA;		*cp++ = TAT_EXTHI;		*cp++ = TAX_RESET;	}	if (f_color != TAC_RESET) {		*cp++ = TO_SA;		*cp++ = TAT_COLOR;		*cp++ = TAC_RESET;	}	if (line->len < tp->view.cols) {		*cp++ = TO_RA;		*cp++ = 0;		*cp++ = 0;		*cp++ = 0;	}	if (tp->nr_up + line_nr < tp->view.rows - 2) {		/* Line is currently visible on screen. */		tty3270_update_string(tp, s, line_nr);		/* Add line to update list. */		if (list_empty(&s->update)) {			list_add_tail(&s->update, &tp->update);			tp->update_flags |= TTY_UPDATE_LIST;		}	}}/* * Do carriage return. */static voidtty3270_cr(struct tty3270 *tp){	tp->cx = 0;}/* * Do line feed. */static voidtty3270_lf(struct tty3270 *tp){	struct tty3270_line temp;	int i;	tty3270_convert_line(tp, tp->cy);	if (tp->cy < tp->view.rows - 3) {		tp->cy++;		return;	}	/* Last line just filled up. Add new, blank line. */	tty3270_blank_line(tp);	temp = tp->screen[0];	temp.len = 0;	for (i = 0; i < tp->view.rows - 3; i++)		tp->screen[i] = tp->screen[i+1];	tp->screen[tp->view.rows - 3] = temp;	tty3270_rebuild_update(tp);}static voidtty3270_ri(struct tty3270 *tp){	if (tp->cy > 0) {	    tty3270_convert_line(tp, tp->cy);	    tp->cy--;	}}/* * Insert characters at current position. */static voidtty3270_insert_characters(struct tty3270 *tp, int n){	struct tty3270_line *line;	int k;	line = tp->screen + tp->cy;	while (line->len < tp->cx) {		line->cells[line->len].character = tp->view.ascebc[' '];		line->cells[line->len].highlight = TAX_RESET;		line->cells[line->len].f_color = TAC_RESET;		line->len++;	}	if (n > tp->view.cols - tp->cx)		n = tp->view.cols - tp->cx;	k = min_t(int, line->len - tp->cx, tp->view.cols - tp->cx - n);	while (k--)		line->cells[tp->cx + n + k] = line->cells[tp->cx + k];	line->len += n;	if (line->len > tp->view.cols)		line->len = tp->view.cols;	while (n-- > 0) {		line->cells[tp->cx + n].character = tp->view.ascebc[' '];		line->cells[tp->cx + n].highlight = tp->highlight;		line->cells[tp->cx + n].f_color = tp->f_color;	}}/* * Delete characters at current position. */static voidtty3270_delete_characters(struct tty3270 *tp, int n){	struct tty3270_line *line;	int i;	line = tp->screen + tp->cy;	if (line->len <= tp->cx)		return;	if (line->len - tp->cx <= n) {		line->len = tp->cx;		return;	}	for (i = tp->cx; i + n < line->len; i++)		line->cells[i] = line->cells[i + n];	line->len -= n;}/* * Erase characters at current position. */static voidtty3270_erase_characters(struct tty3270 *tp, int n){	struct tty3270_line *line;	struct tty3270_cell *cell;	line = tp->screen + tp->cy;	while (line->len > tp->cx && n-- > 0) {		cell = line->cells + tp->cx++;		cell->character = ' ';		cell->highlight = TAX_RESET;		cell->f_color = TAC_RESET;	}	tp->cx += n;	tp->cx = min_t(int, tp->cx, tp->view.cols - 1);}/* * Erase line, 3 different cases: *  Esc [ 0 K	Erase from current position to end of line inclusive *  Esc [ 1 K	Erase from beginning of line to current position inclusive *  Esc [ 2 K	Erase entire line (without moving cursor) */static void

⌨️ 快捷键说明

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