raw3270.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,318 行 · 第 1/3 页

C
1,318
字号
		char  xmin;		char  ymin;		char  xmax;		char  ymax;	} __attribute__ ((packed)) uab;	struct {	/* Alternate Usable Area Self-Defining Parameter */		char  l;	/* Length of this Self-Defining Parm */		char  sdpid;	/* 0x02 if Alternate Usable Area */		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;} __attribute__ ((packed));static unsigned char raw3270_init_data[256];static struct raw3270_request raw3270_init_request;static struct diag210 raw3270_init_diag210;static DECLARE_MUTEX(raw3270_init_sem);static intraw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,		 struct irb *irb){	/*	 * Unit-Check Processing:	 * Expect Command Reject or Intervention Required.	 */	if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {		/* Request finished abnormally. */		if (irb->ecw[0] & SNS0_INTERVENTION_REQ) {			set_bit(RAW3270_FLAGS_BUSY, &view->dev->flags);			return RAW3270_IO_BUSY;		}	}	if (rq) {		if (irb->scsw.dstat & DEV_STAT_UNIT_CHECK) {			if (irb->ecw[0] & SNS0_CMD_REJECT)				rq->rc = -EOPNOTSUPP;			else				rq->rc = -EIO;		} else			/* Request finished normally. Copy residual count. */			rq->rescnt = irb->scsw.count;	}	if (irb->scsw.dstat & DEV_STAT_ATTENTION) {		set_bit(RAW3270_FLAGS_ATTN, &view->dev->flags);		wake_up(&raw3270_wait_queue);	}	return RAW3270_IO_DONE;}static struct raw3270_fn raw3270_init_fn = {	.intv = raw3270_init_irq};static struct raw3270_view raw3270_init_view = {	.fn = &raw3270_init_fn};/* * raw3270_wait/raw3270_wait_interruptible/__raw3270_wakeup * Wait for end of request. The request must have been started * with raw3270_start, rc = 0. The device lock may NOT have been * released between calling raw3270_start and raw3270_wait. */static voidraw3270_wake_init(struct raw3270_request *rq, void *data){	wake_up((wait_queue_head_t *) data);}/* * Special wait function that can cope with console initialization. */static intraw3270_start_init(struct raw3270 *rp, struct raw3270_view *view,		   struct raw3270_request *rq){	unsigned long flags;	wait_queue_head_t wq;	int rc;#ifdef CONFIG_TN3270_CONSOLE	if (raw3270_registered == 0) {		spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);		rq->callback = 0;		rc = __raw3270_start(rp, view, rq);		if (rc == 0)			while (!raw3270_request_final(rq)) {				wait_cons_dev();				barrier();			}		spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);		return rq->rc;	}#endif	init_waitqueue_head(&wq);	rq->callback = raw3270_wake_init;	rq->callback_data = &wq;	spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);	rc = __raw3270_start(rp, view, rq);	spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);	if (rc)		return rc;	/* Now wait for the completion. */	rc = wait_event_interruptible(wq, raw3270_request_final(rq));	if (rc == -ERESTARTSYS) {	/* Interrupted by a signal. */		raw3270_halt_io(view->dev, rq);		return -ERESTARTSYS;	}	return rq->rc;}static int__raw3270_size_device_vm(struct raw3270 *rp){	int rc, model;	raw3270_init_diag210.vrdcdvno = 		_ccw_device_get_device_number(rp->cdev);	raw3270_init_diag210.vrdclen = sizeof(struct diag210);	rc = diag210(&raw3270_init_diag210);	if (rc)		return rc;	model = raw3270_init_diag210.vrdccrmd;	switch (model) {	case 2:		rp->model = model;		rp->rows = 24;		rp->cols = 80;		break;	case 3:		rp->model = model;		rp->rows = 32;		rp->cols = 80;		break;	case 4:		rp->model = model;		rp->rows = 43;		rp->cols = 80;		break;	case 5:		rp->model = model;		rp->rows = 27;		rp->cols = 132;		break;	default:		printk(KERN_WARNING "vrdccrmd is 0x%.8x\n", model);		rc = -EOPNOTSUPP;		break;	}	return rc;}static int__raw3270_size_device(struct raw3270 *rp){	static const unsigned char wbuf[] =		{ 0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81 };	struct raw3270_ua *uap;	unsigned short count;	int rc;	/*	 * To determine the size of the 3270 device we need to do:	 * 1) send a 'read partition' data stream to the device	 * 2) wait for the attn interrupt that preceeds the query reply	 * 3) do a read modified to get the query reply	 * To make things worse we have to cope with intervention	 * required (3270 device switched to 'stand-by') and command	 * rejects (old devices that can't do 'read partition').	 */	memset(&raw3270_init_request, 0, sizeof(raw3270_init_request));	memset(raw3270_init_data, 0, sizeof(raw3270_init_data));	/* Store 'read partition' data stream to raw3270_init_data */	memcpy(raw3270_init_data, wbuf, sizeof(wbuf));	INIT_LIST_HEAD(&raw3270_init_request.list);	raw3270_init_request.ccw.cmd_code = TC_WRITESF;	raw3270_init_request.ccw.flags = CCW_FLAG_SLI;	raw3270_init_request.ccw.count = sizeof(wbuf);	raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);	rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);	if (rc) {		/* Check error cases: -ERESTARTSYS, -EIO and -EOPNOTSUPP */		if (rc == -EOPNOTSUPP && MACHINE_IS_VM)			return __raw3270_size_device_vm(rp);		return rc;	}	/* Wait for attention interrupt. */#ifdef CONFIG_TN3270_CONSOLE	if (raw3270_registered == 0) {		unsigned long flags;		spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);		while (!test_and_clear_bit(RAW3270_FLAGS_ATTN, &rp->flags))			wait_cons_dev();		spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);	} else#endif		rc = wait_event_interruptible(raw3270_wait_queue,			test_and_clear_bit(RAW3270_FLAGS_ATTN, &rp->flags));	if (rc)		return rc;	/*	 * The device accepted the 'read partition' command. Now	 * set up a read ccw and issue it.	 */	raw3270_init_request.ccw.cmd_code = TC_READMOD;	raw3270_init_request.ccw.flags = CCW_FLAG_SLI;	raw3270_init_request.ccw.count = sizeof(raw3270_init_data);	raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);	rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);	if (rc)		return rc;	/* Got a Query Reply */	count = sizeof(raw3270_init_data) - raw3270_init_request.rescnt;	uap = (struct raw3270_ua *) (raw3270_init_data + 1);	/* Paranoia check. */	if (raw3270_init_data[0] != 0x88 || uap->uab.qcode != 0x81)		return -EOPNOTSUPP;	/* Copy rows/columns of default Usable Area */	rp->rows = uap->uab.h;	rp->cols = uap->uab.w;	/* Check for 14 bit addressing */	if ((uap->uab.flags0 & 0x0d) == 0x01)		set_bit(RAW3270_FLAGS_14BITADDR, &rp->flags);	/* Check for Alternate Usable Area */	if (uap->uab.l == sizeof(struct raw3270_ua) &&	    uap->aua.sdpid == 0x02) {		rp->rows = uap->aua.hauai;		rp->cols = uap->aua.wauai;	}	return 0;}static intraw3270_size_device(struct raw3270 *rp){	int rc;	down(&raw3270_init_sem);	rp->view = &raw3270_init_view;	raw3270_init_view.dev = rp;	rc = __raw3270_size_device(rp);	raw3270_init_view.dev = 0;	rp->view = 0;	up(&raw3270_init_sem);	if (rc == 0) {	/* Found something. */		/* Try to find a model. */		rp->model = 0;		if (rp->rows == 24 && rp->cols == 80)			rp->model = 2;		if (rp->rows == 32 && rp->cols == 80)			rp->model = 3;		if (rp->rows == 43 && rp->cols == 80)			rp->model = 4;		if (rp->rows == 27 && rp->cols == 132)			rp->model = 5;	}	return rc;}static intraw3270_reset_device(struct raw3270 *rp){	int rc;	down(&raw3270_init_sem);	memset(&raw3270_init_request, 0, sizeof(raw3270_init_request));	memset(raw3270_init_data, 0, sizeof(raw3270_init_data));	/* Store reset data stream to raw3270_init_data/raw3270_init_request */	raw3270_init_data[0] = TW_KR;	INIT_LIST_HEAD(&raw3270_init_request.list);	raw3270_init_request.ccw.cmd_code = TC_EWRITEA;	raw3270_init_request.ccw.flags = CCW_FLAG_SLI;	raw3270_init_request.ccw.count = 1;	raw3270_init_request.ccw.cda = (__u32) __pa(raw3270_init_data);	rp->view = &raw3270_init_view;	raw3270_init_view.dev = rp;	rc = raw3270_start_init(rp, &raw3270_init_view, &raw3270_init_request);	raw3270_init_view.dev = 0;	rp->view = 0;	up(&raw3270_init_sem);	return rc;}/* * Setup new 3270 device. */static intraw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc){	struct list_head *l;	struct raw3270 *tmp;	int minor;	memset(rp, 0, sizeof(struct raw3270));	/* Copy ebcdic -> ascii translation table. */	memcpy(ascebc, _ascebc, 256);	if (tubxcorrect) {		/* correct brackets and circumflex */		ascebc['['] = 0xad;		ascebc[']'] = 0xbd;		ascebc['^'] = 0xb0;	}	rp->ascebc = ascebc;	/* Set defaults. */	rp->rows = 24;	rp->cols = 80;	INIT_LIST_HEAD(&rp->req_queue);	INIT_LIST_HEAD(&rp->view_list);	/*	 * Add device to list and find the smallest unused minor	 * number for it.	 */	down(&raw3270_sem);	/* Keep the list sorted. */	minor = 0;	rp->minor = -1;	list_for_each(l, &raw3270_devices) {		tmp = list_entry(l, struct raw3270, list);		if (tmp->minor > minor) {			rp->minor = minor;			__list_add(&rp->list, l->prev, l);			break;		}		minor++;	}	if (rp->minor == -1 && minor < RAW3270_MAXDEVS) {		rp->minor = minor;		list_add_tail(&rp->list, &raw3270_devices);	}	up(&raw3270_sem);	/* No free minor number? Then give up. */	if (rp->minor == -1)		return -EUSERS;	rp->cdev = cdev;	cdev->dev.driver_data = rp;	cdev->handler = raw3270_irq;	return 0;}#ifdef CONFIG_TN3270_CONSOLE/* * Setup 3270 device configured as console. */struct raw3270 *raw3270_setup_console(struct ccw_device *cdev){	struct raw3270 *rp;	char *ascebc;	int rc;	rp = (struct raw3270 *) alloc_bootmem(sizeof(struct raw3270));	ascebc = (char *) alloc_bootmem(256);	rc = raw3270_setup_device(cdev, rp, ascebc);	if (rc)		return ERR_PTR(rc);	set_bit(RAW3270_FLAGS_CONSOLE, &rp->flags);	raw3270_reset_device(rp);	raw3270_size_device(rp);	raw3270_reset_device(rp);	set_bit(RAW3270_FLAGS_READY, &rp->flags);	return rp;}voidraw3270_wait_cons_dev(struct raw3270 *rp){	unsigned long flags;	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);	wait_cons_dev();	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);}#endif/* * Create a 3270 device structure. */static struct raw3270 *raw3270_create_device(struct ccw_device *cdev){	struct raw3270 *rp;	char *ascebc;	int rc;	rp = kmalloc(sizeof(struct raw3270), GFP_KERNEL);	if (!rp)		return ERR_PTR(-ENOMEM);	ascebc = kmalloc(256, GFP_KERNEL);	if (!ascebc) {		kfree(rp);		return ERR_PTR(-ENOMEM);	}	rc = raw3270_setup_device(cdev, rp, ascebc);	if (rc) {		kfree(rp->ascebc);		kfree(rp);		rp = ERR_PTR(rc);	}	/* Get reference to ccw_device structure. */	get_device(&cdev->dev);	return rp;}/* * Activate a view. */intraw3270_activate_view(struct raw3270_view *view){	struct raw3270 *rp;	struct raw3270_view *oldview, *nv;	unsigned long flags;	int rc;	rp = view->dev;	if (!rp)		return -ENODEV;	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);	if (rp->view == view)		rc = 0;	else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags))		rc = -ENODEV;	else {		oldview = 0;

⌨️ 快捷键说明

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