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

📄 tubttysiz.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
字号:
/* *  IBM/3270 Driver -- Copyright (C) 2000 UTS Global LLC * *  tubttysiz.c -- Linemode screen-size determiner * * * * * *  Author:  Richard Hitt */#include "tubio.h"static int tty3270_size_io(tub_t *tubp);static void tty3270_size_int(tub_t *tubp, devstat_t *dsp);static int tty3270_size_wait(tub_t *tubp, long *flags, int stat);/* * Structure representing Usable Area Query Reply Base */typedef struct {	short l;                /* Length of this structured field */	char sfid;              /* 0x81 if Query Reply */	char qcode;             /* 0x81 if Usable Area */#define QCODE_UA 0x81	char flags0;#define FLAGS0_ADDR 0x0f#define FLAGS0_ADDR_12_14       1       /* 12/14-bit adrs ok */#define FLAGS0_ADDR_12_14_16    3       /* 12/14/16-bit adrs ok */	char flags1;	short w;                /* Width of usable area */	short h;                /* Heigth of usavle area */	char units;             /* 0x00:in; 0x01:mm */	int xr;	int yr;	char aw;	char ah;	short buffsz;           /* Character buffer size, bytes */	char xmin;	char ymin;	char xmax;	char ymax;} __attribute__ ((packed)) uab_t;/* * Structure representing Alternate Usable Area Self-Defining Parameter */typedef struct {	char l;                 /* Length of this Self-Defining Parm */	char sdpid;             /* 0x02 if Alternate Usable Area */#define SDPID_AUA 0x02	char res;	char auaid;             /* 0x01 is Id for the A U A */	short wauai;            /* Width of AUAi */	short hauai;            /* Height of AUAi */	char auaunits;          /* 0x00:in, 0x01:mm */	int auaxr;	int auayr;	char awauai;	char ahauai;} __attribute__ ((packed)) aua_t;/* * Structure representing one followed by the other */typedef struct {	uab_t uab;	aua_t aua;} __attribute__ ((packed)) ua_t;/* * Try to determine screen size using Read Partition (Query) */inttty3270_size(tub_t *tubp, long *flags){	char wbuf[7] = { 0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81 };	int     rc = 0;	int     count;	unsigned char *cp;	ua_t *uap;	char miniscreen[256];	char (*screen)[];	int screenl;	int geom_rows, geom_cols, fourteenbitadr;	void (*oldint)(struct tub_s *, devstat_t *);	if (tubp->flags & TUB_SIZED)		return 0;	fourteenbitadr = 0;	geom_rows = tubp->geom_rows;	geom_cols = tubp->geom_cols;	oldint = tubp->intv;	tubp->intv = tty3270_size_int;	if (tubp->cmd == TBC_CONOPEN) {		tubp->ttyccw.cmd_code = TC_EWRITEA;		cp = miniscreen;		*cp++ = TW_KR;		/* more? */		tubp->ttyccw.flags = CCW_FLAG_SLI;		tubp->ttyccw.cda = virt_to_phys(miniscreen);		tubp->ttyccw.count = (char *)cp - miniscreen;		rc = tty3270_size_io(tubp);		rc = tty3270_size_wait(tubp, flags, 0);	}	tubp->ttyccw.cmd_code = TC_WRITESF;	tubp->ttyccw.flags = CCW_FLAG_SLI;	tubp->ttyccw.cda = virt_to_phys(wbuf);	tubp->ttyccw.count = sizeof wbuf;try_again:	rc = tty3270_size_io(tubp);	if (rc)		printk("tty3270_size_io returned %d\n", rc);	rc = tty3270_size_wait(tubp, flags, 0);	if (rc != 0) {		goto do_return;	}	/*	 * Unit-Check Processing:	 * Expect Command Reject or Intervention Required.	 * For Command Reject assume old hdwe/software and	 * set a default size of 80x24.	 * For Intervention Required, wait for signal pending	 * or Unsolicited Device End; if the latter, retry.	 */	if (tubp->dstat & DEV_STAT_UNIT_CHECK) {		if (tubp->sense.data[0] & SNS0_CMD_REJECT) {			goto use_diag210; /* perhaps it's tn3270 */		} else if (tubp->sense.data[0] & SNS0_INTERVENTION_REQ) {			if ((rc = tty3270_size_wait(tubp, flags,			    DEV_STAT_DEV_END)))				goto do_return;			goto try_again;		} else {			printk("tty3270_size(): unkn sense %.2x\n",				tubp->sense.data[0]);			goto do_return;		}	}	if ((rc = tty3270_size_wait(tubp, flags, DEV_STAT_ATTENTION)))		goto do_return;	/* Set up a read ccw and issue it */	tubp->ttyccw.cmd_code = TC_READMOD;	tubp->ttyccw.flags = CCW_FLAG_SLI;	tubp->ttyccw.cda = virt_to_phys(miniscreen);	tubp->ttyccw.count = sizeof miniscreen;	tty3270_size_io(tubp);	rc = tty3270_size_wait(tubp, flags, 0);	if (rc != 0)		goto do_return;	count = sizeof miniscreen - tubp->cswl;	cp = miniscreen;	if (*cp++ != 0x88)		goto do_return;	uap = (void *)cp;	if (uap->uab.qcode != QCODE_UA)		goto do_return;	geom_rows = uap->uab.h;	geom_cols = uap->uab.w;	if ((uap->uab.flags0 & FLAGS0_ADDR) == FLAGS0_ADDR_12_14 ||	    (uap->uab.flags0 & FLAGS0_ADDR) == FLAGS0_ADDR_12_14_16)		fourteenbitadr = 1;	if (uap->uab.l <= sizeof uap->uab)		goto do_return;	if (uap->aua.sdpid != SDPID_AUA) {		printk("AUA sdpid was 0x%.2x, expecting 0x%.2x\n",			uap->aua.sdpid, SDPID_AUA);		goto do_return;	}	geom_rows = uap->aua.hauai;	geom_cols = uap->aua.wauai;	goto do_return;use_diag210:	if (MACHINE_IS_VM) {		diag210_t d210;		d210.vrdcdvno = tubp->devno;		d210.vrdclen = sizeof d210;		rc = diag210(&d210);		if (rc) {			printk("tty3270_size: diag210 for 0x%.4x "				"returned %d\n", tubp->devno, rc);			goto do_return;		}		switch(d210.vrdccrmd) {		case 2:			geom_rows = 24;			geom_cols = 80;			goto do_return;		case 3:			geom_rows = 32;			geom_cols = 80;			goto do_return;		case 4:			geom_rows = 43;			geom_cols = 80;			goto do_return;		case 5:			geom_rows = 27;			geom_cols = 132;			goto do_return;		default:			printk("vrdccrmd is 0x%.8x\n", d210.vrdccrmd);		}	}do_return:	if (geom_rows == 0) {		geom_rows = _GEOM_ROWS;		geom_cols = _GEOM_COLS;	}	tubp->tubiocb.pf_cnt = 24;	tubp->tubiocb.re_cnt = 20;	tubp->tubiocb.map = 0;	screenl = geom_rows * geom_cols + 100;	screen = (char (*)[])kmalloc(screenl, GFP_KERNEL);	if (screen == NULL) {		printk("ttyscreen size %d unavailable\n", screenl);	} else {		if (tubp->ttyscreen)			kfree(tubp->ttyscreen);		tubp->tubiocb.line_cnt = tubp->geom_rows = geom_rows;		tubp->tubiocb.col_cnt = tubp->geom_cols = geom_cols;		tubp->tty_14bitadr = fourteenbitadr;		tubp->ttyscreen = screen;		tubp->ttyscreenl = screenl;		if (geom_rows == 24 && geom_cols == 80)			tubp->tubiocb.model = 2;		else if (geom_rows == 32 && geom_cols == 80)			tubp->tubiocb.model = 3;		else if (geom_rows == 43 && geom_cols == 80)			tubp->tubiocb.model = 4;		else if (geom_rows == 27 && geom_cols == 132)			tubp->tubiocb.model = 5;		else			tubp->tubiocb.model = 0;		tubp->flags |= TUB_SIZED;	}	if (rc == 0 && tubp->ttyscreen == NULL)		rc = -ENOMEM;	tubp->intv = oldint;	return rc;}static inttty3270_size_io(tub_t *tubp){	tubp->flags |= TUB_WORKING;	tubp->dstat = 0;	return do_IO(tubp->irq, &tubp->ttyccw, tubp->irq, 0, 0);}static voidtty3270_size_int(tub_t *tubp, devstat_t *dsp){#define DEV_NOT_WORKING \  (DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_CHECK)	tubp->dstat = dsp->dstat;	if (dsp->dstat & DEV_STAT_CHN_END)		tubp->cswl = dsp->rescnt;	if (dsp->dstat & DEV_NOT_WORKING)		tubp->flags &= ~TUB_WORKING;	if (dsp->dstat & DEV_STAT_UNIT_CHECK)		tubp->sense = dsp->ii.sense;	wake_up_interruptible(&tubp->waitq);}/* * Wait for something.  If the third arg is zero, wait until * tty3270_size_int() turns off TUB_WORKING.  If the third arg * is not zero, it is a device-status bit; wait until dstat * has the bit turned on.  Never wait if signal is pending. * Return 0 unless signal pending, in which case -ERESTARTSYS. */static inttty3270_size_wait(tub_t *tubp, long *flags, int stat){	DECLARE_WAITQUEUE(wait, current);	add_wait_queue(&tubp->waitq, &wait);	while (!signal_pending(current) &&	    (stat? (tubp->dstat & stat) == 0:	     (tubp->flags & TUB_WORKING) != 0)) {		current->state = TASK_INTERRUPTIBLE;		TUBUNLOCK(tubp->irq, *flags);		schedule();		current->state = TASK_RUNNING;		TUBLOCK(tubp->irq, *flags);	}	remove_wait_queue(&tubp->waitq, &wait);	return signal_pending(current)? -ERESTARTSYS: 0;}

⌨️ 快捷键说明

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