Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)  * IBM/3270 Driver - core functions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)  * Author(s):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6)  *   Original 3270 Code for 2.4 written by Richard Hitt (UTS Global)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)  *   Rewritten for 2.5 by Martin Schwidefsky <schwidefsky@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)  *     Copyright IBM Corp. 2003, 2009
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) #include <asm/ccwdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21) #include <asm/cio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22) #include <asm/ebcdic.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23) #include <asm/diag.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25) #include "raw3270.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27) #include <linux/major.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28) #include <linux/kdev_t.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) struct class *class3270;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) /* The main 3270 data structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) struct raw3270 {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) 	struct list_head list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) 	struct ccw_device *cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) 	int minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) 	short model, rows, cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) 	unsigned int state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) 	struct list_head req_queue;	/* Request queue. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) 	struct list_head view_list;	/* List of available views. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) 	struct raw3270_view *view;	/* Active view. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) 	struct timer_list timer;	/* Device timer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) 	unsigned char *ascebc;		/* ascii -> ebcdic table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) 	struct raw3270_view init_view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 	struct raw3270_request init_reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) 	struct raw3270_request init_readpart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 	struct raw3270_request init_readmod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) 	unsigned char init_data[256];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) /* raw3270->state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #define RAW3270_STATE_INIT	0	/* Initial state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) #define RAW3270_STATE_RESET	1	/* Reset command is pending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) #define RAW3270_STATE_W4ATTN	2	/* Wait for attention interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) #define RAW3270_STATE_READMOD	3	/* Read partition is pending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) #define RAW3270_STATE_READY	4	/* Device is usable by views */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66) /* raw3270->flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) #define RAW3270_FLAGS_14BITADDR	0	/* 14-bit buffer addresses */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68) #define RAW3270_FLAGS_BUSY	1	/* Device busy, leave it alone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69) #define RAW3270_FLAGS_CONSOLE	2	/* Device is the console. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) #define RAW3270_FLAGS_FROZEN	3	/* set if 3270 is frozen for suspend */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) /* Semaphore to protect global data of raw3270 (devices, views, etc). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) static DEFINE_MUTEX(raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) /* List of 3270 devices. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) static LIST_HEAD(raw3270_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79)  * Flag to indicate if the driver has been registered. Some operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80)  * like waiting for the end of i/o need to be done differently as long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81)  * as the kernel is still starting up (console support).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) static int raw3270_registered;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) /* Module parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) static bool tubxcorrect;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) module_param(tubxcorrect, bool, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90)  * Wait queue for device init/delete, view delete.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) DECLARE_WAIT_QUEUE_HEAD(raw3270_wait_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) static void __raw3270_disconnect(struct raw3270 *rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97)  * Encode array for 12 bit 3270 addresses.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) static unsigned char raw3270_ebcgraf[64] =	{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) 	0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) 	0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) 	0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) 	0xd8, 0xd9, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) 	0x60, 0x61, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 	0xe8, 0xe9, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) 	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) 	0xf8, 0xf9, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) static inline int raw3270_state_ready(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) 	return rp->state == RAW3270_STATE_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) static inline int raw3270_state_final(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) 	return rp->state == RAW3270_STATE_INIT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) 		rp->state == RAW3270_STATE_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) raw3270_buffer_address(struct raw3270 *rp, char *cp, unsigned short addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) 	if (test_bit(RAW3270_FLAGS_14BITADDR, &rp->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) 		cp[0] = (addr >> 8) & 0x3f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) 		cp[1] = addr & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) 		cp[0] = raw3270_ebcgraf[(addr >> 6) & 0x3f];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) 		cp[1] = raw3270_ebcgraf[addr & 0x3f];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134)  * Allocate a new 3270 ccw request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136) struct raw3270_request *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137) raw3270_request_alloc(size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 	struct raw3270_request *rq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141) 	/* Allocate request structure */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) 	rq = kzalloc(sizeof(struct raw3270_request), GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 	if (!rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146) 	/* alloc output buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147) 	if (size > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148) 		rq->buffer = kmalloc(size, GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149) 		if (!rq->buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150) 			kfree(rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151) 			return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154) 	rq->size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) 	INIT_LIST_HEAD(&rq->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) 	 * Setup ccw.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160) 	rq->ccw.cda = __pa(rq->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) 	rq->ccw.flags = CCW_FLAG_SLI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) 	return rq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167)  * Free 3270 ccw request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) raw3270_request_free (struct raw3270_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 	kfree(rq->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) 	kfree(rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177)  * Reset request to initial state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) raw3270_request_reset(struct raw3270_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) 	BUG_ON(!list_empty(&rq->list));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) 	rq->ccw.cmd_code = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) 	rq->ccw.count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) 	rq->ccw.cda = __pa(rq->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) 	rq->ccw.flags = CCW_FLAG_SLI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) 	rq->rescnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) 	rq->rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192)  * Set command code to ccw of a request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) raw3270_request_set_cmd(struct raw3270_request *rq, u8 cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) 	rq->ccw.cmd_code = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201)  * Add data fragment to output buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204) raw3270_request_add_data(struct raw3270_request *rq, void *data, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206) 	if (size + rq->ccw.count > rq->size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207) 		return -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208) 	memcpy(rq->buffer + rq->ccw.count, data, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) 	rq->ccw.count += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214)  * Set address/length pair to ccw of a request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) raw3270_request_set_data(struct raw3270_request *rq, void *data, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219) 	rq->ccw.cda = __pa(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220) 	rq->ccw.count = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224)  * Set idal buffer to ccw of a request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) raw3270_request_set_idal(struct raw3270_request *rq, struct idal_buffer *ib)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) 	rq->ccw.cda = __pa(ib->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 	rq->ccw.count = ib->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) 	rq->ccw.flags |= CCW_FLAG_IDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235)  * Add the request to the request queue, try to start it if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236)  * 3270 device is idle. Return without waiting for end of i/o.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) __raw3270_start(struct raw3270 *rp, struct raw3270_view *view,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240) 		struct raw3270_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 	rq->view = view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) 	raw3270_get_view(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) 	if (list_empty(&rp->req_queue) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245) 	    !test_bit(RAW3270_FLAGS_BUSY, &rp->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246) 		/* No other requests are on the queue. Start this one. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247) 		rq->rc = ccw_device_start(rp->cdev, &rq->ccw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) 					       (unsigned long) rq, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 		if (rq->rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) 			raw3270_put_view(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) 			return rq->rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254) 	list_add_tail(&rq->list, &rp->req_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259) raw3270_view_active(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	struct raw3270 *rp = view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	return rp && rp->view == view &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264) 		!test_bit(RAW3270_FLAGS_FROZEN, &rp->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) raw3270_start(struct raw3270_view *view, struct raw3270_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 	spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) 	rp = view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) 	if (!rp || rp->view != view ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277) 	    test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278) 		rc = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) 	else if (!raw3270_state_ready(rp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 		rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 		rc =  __raw3270_start(rp, view, rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283) 	spin_unlock_irqrestore(get_ccwdev_lock(view->dev->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288) raw3270_start_locked(struct raw3270_view *view, struct raw3270_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 	rp = view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) 	if (!rp || rp->view != view ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) 	    test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296) 		rc = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297) 	else if (!raw3270_state_ready(rp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298) 		rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300) 		rc =  __raw3270_start(rp, view, rq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) raw3270_start_irq(struct raw3270_view *view, struct raw3270_request *rq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309) 	rp = view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 	rq->view = view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311) 	raw3270_get_view(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312) 	list_add_tail(&rq->list, &rp->req_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317)  * 3270 interrupt routine, called from the ccw_device layer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) raw3270_irq (struct ccw_device *cdev, unsigned long intparm, struct irb *irb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323) 	struct raw3270_view *view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324) 	struct raw3270_request *rq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 	rp = dev_get_drvdata(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327) 	if (!rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329) 	rq = (struct raw3270_request *) intparm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330) 	view = rq ? rq->view : rp->view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	if (!IS_ERR(irb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333) 		/* Handle CE-DE-UE and subsequent UDE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 		if (irb->scsw.cmd.dstat & DEV_STAT_DEV_END)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335) 			clear_bit(RAW3270_FLAGS_BUSY, &rp->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 		if (irb->scsw.cmd.dstat == (DEV_STAT_CHN_END |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337) 					    DEV_STAT_DEV_END |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 					    DEV_STAT_UNIT_EXCEP))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339) 			set_bit(RAW3270_FLAGS_BUSY, &rp->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 		/* Handle disconnected devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341) 		if ((irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 		    (irb->ecw[0] & SNS0_INTERVENTION_REQ)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 			set_bit(RAW3270_FLAGS_BUSY, &rp->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344) 			if (rp->state > RAW3270_STATE_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345) 				__raw3270_disconnect(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 		/* Call interrupt handler of the view */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348) 		if (view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349) 			view->fn->intv(view, rq, irb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	if (test_bit(RAW3270_FLAGS_BUSY, &rp->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 		/* Device busy, do not start I/O */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	if (rq && !list_empty(&rq->list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 		/* The request completed, remove from queue and do callback. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 		list_del_init(&rq->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 		if (rq->callback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 			rq->callback(rq, rq->callback_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 		/* Do put_device for get_device in raw3270_start. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 		raw3270_put_view(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366) 	 * Try to start each request on request queue until one is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367) 	 * started successful.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 	while (!list_empty(&rp->req_queue)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) 		rq = list_entry(rp->req_queue.next,struct raw3270_request,list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 		rq->rc = ccw_device_start(rp->cdev, &rq->ccw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372) 					  (unsigned long) rq, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373) 		if (rq->rc == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375) 		/* Start failed. Remove request and do callback. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) 		list_del_init(&rq->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 		if (rq->callback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) 			rq->callback(rq, rq->callback_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) 		/* Do put_device for get_device in raw3270_start. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380) 		raw3270_put_view(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385)  * To determine the size of the 3270 device we need to do:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386)  * 1) send a 'read partition' data stream to the device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387)  * 2) wait for the attn interrupt that precedes the query reply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388)  * 3) do a read modified to get the query reply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389)  * To make things worse we have to cope with intervention
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390)  * required (3270 device switched to 'stand-by') and command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391)  * rejects (old devices that can't do 'read partition').
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) struct raw3270_ua {	/* Query Reply structure for Usable Area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) 	struct {	/* Usable Area Query Reply Base */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) 		short l;	/* Length of this structured field */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396) 		char  sfid;	/* 0x81 if Query Reply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397) 		char  qcode;	/* 0x81 if Usable Area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398) 		char  flags0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399) 		char  flags1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400) 		short w;	/* Width of usable area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 		short h;	/* Heigth of usavle area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402) 		char  units;	/* 0x00:in; 0x01:mm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 		int   xr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404) 		int   yr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 		char  aw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 		char  ah;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 		short buffsz;	/* Character buffer size, bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 		char  xmin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 		char  ymin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 		char  xmax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 		char  ymax;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	} __attribute__ ((packed)) uab;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	struct {	/* Alternate Usable Area Self-Defining Parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 		char  l;	/* Length of this Self-Defining Parm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415) 		char  sdpid;	/* 0x02 if Alternate Usable Area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416) 		char  res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) 		char  auaid;	/* 0x01 is Id for the A U A */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 		short wauai;	/* Width of AUAi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) 		short hauai;	/* Height of AUAi */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 		char  auaunits;	/* 0x00:in, 0x01:mm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421) 		int   auaxr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422) 		int   auayr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) 		char  awauai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 		char  ahauai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) 	} __attribute__ ((packed)) aua;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) } __attribute__ ((packed));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) raw3270_size_device_vm(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	int rc, model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) 	struct ccw_dev_id dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 	struct diag210 diag_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) 	ccw_device_get_id(rp->cdev, &dev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436) 	diag_data.vrdcdvno = dev_id.devno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437) 	diag_data.vrdclen = sizeof(struct diag210);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	rc = diag210(&diag_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439) 	model = diag_data.vrdccrmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	/* Use default model 2 if the size could not be detected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	if (rc || model < 2 || model > 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442) 		model = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443) 	switch (model) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 		rp->model = model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) 		rp->rows = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 		rp->cols = 80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) 	case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450) 		rp->model = model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451) 		rp->rows = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452) 		rp->cols = 80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454) 	case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 		rp->model = model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 		rp->rows = 43;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 		rp->cols = 80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 		rp->model = model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 		rp->rows = 27;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 		rp->cols = 132;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468) raw3270_size_device(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) 	struct raw3270_ua *uap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) 	/* Got a Query Reply */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 	uap = (struct raw3270_ua *) (rp->init_data + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474) 	/* Paranoia check. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475) 	if (rp->init_readmod.rc || rp->init_data[0] != 0x88 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) 	    uap->uab.qcode != 0x81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 		/* Couldn't detect size. Use default model 2. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) 		rp->model = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) 		rp->rows = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 		rp->cols = 80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483) 	/* Copy rows/columns of default Usable Area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484) 	rp->rows = uap->uab.h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485) 	rp->cols = uap->uab.w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486) 	/* Check for 14 bit addressing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) 	if ((uap->uab.flags0 & 0x0d) == 0x01)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 		set_bit(RAW3270_FLAGS_14BITADDR, &rp->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) 	/* Check for Alternate Usable Area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) 	if (uap->uab.l == sizeof(struct raw3270_ua) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491) 	    uap->aua.sdpid == 0x02) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492) 		rp->rows = uap->aua.hauai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 		rp->cols = uap->aua.wauai;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495) 	/* Try to find a model. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496) 	rp->model = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497) 	if (rp->rows == 24 && rp->cols == 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 		rp->model = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	if (rp->rows == 32 && rp->cols == 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 		rp->model = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501) 	if (rp->rows == 43 && rp->cols == 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 		rp->model = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503) 	if (rp->rows == 27 && rp->cols == 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504) 		rp->model = 5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508) raw3270_size_device_done(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510) 	struct raw3270_view *view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512) 	rp->view = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513) 	rp->state = RAW3270_STATE_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514) 	/* Notify views about new size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) 	list_for_each_entry(view, &rp->view_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 		if (view->fn->resize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) 			view->fn->resize(view, rp->model, rp->rows, rp->cols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) 	/* Setup processing done, now activate a view */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519) 	list_for_each_entry(view, &rp->view_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520) 		rp->view = view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 		if (view->fn->activate(view) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) 		rp->view = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528) raw3270_read_modified_cb(struct raw3270_request *rq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	struct raw3270 *rp = rq->view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	raw3270_size_device(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 	raw3270_size_device_done(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537) raw3270_read_modified(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539) 	if (rp->state != RAW3270_STATE_W4ATTN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	/* Use 'read modified' to get the result of a read partition. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542) 	memset(&rp->init_readmod, 0, sizeof(rp->init_readmod));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	memset(&rp->init_data, 0, sizeof(rp->init_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	rp->init_readmod.ccw.cmd_code = TC_READMOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	rp->init_readmod.ccw.flags = CCW_FLAG_SLI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 	rp->init_readmod.ccw.count = sizeof(rp->init_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	rp->init_readmod.ccw.cda = (__u32) __pa(rp->init_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	rp->init_readmod.callback = raw3270_read_modified_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	rp->state = RAW3270_STATE_READMOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550) 	raw3270_start_irq(&rp->init_view, &rp->init_readmod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) raw3270_writesf_readpart(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556) 	static const unsigned char wbuf[] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557) 		{ 0x00, 0x07, 0x01, 0xff, 0x03, 0x00, 0x81 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) 	/* Store 'read partition' data stream to init_data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 	memset(&rp->init_readpart, 0, sizeof(rp->init_readpart));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) 	memset(&rp->init_data, 0, sizeof(rp->init_data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 	memcpy(&rp->init_data, wbuf, sizeof(wbuf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) 	rp->init_readpart.ccw.cmd_code = TC_WRITESF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 	rp->init_readpart.ccw.flags = CCW_FLAG_SLI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) 	rp->init_readpart.ccw.count = sizeof(wbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) 	rp->init_readpart.ccw.cda = (__u32) __pa(&rp->init_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567) 	rp->state = RAW3270_STATE_W4ATTN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) 	raw3270_start_irq(&rp->init_view, &rp->init_readpart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572)  * Device reset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575) raw3270_reset_device_cb(struct raw3270_request *rq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577) 	struct raw3270 *rp = rq->view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579) 	if (rp->state != RAW3270_STATE_RESET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581) 	if (rq->rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582) 		/* Reset command failed. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 		rp->state = RAW3270_STATE_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	} else if (MACHINE_IS_VM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 		raw3270_size_device_vm(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586) 		raw3270_size_device_done(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587) 	} else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588) 		raw3270_writesf_readpart(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 	memset(&rp->init_reset, 0, sizeof(rp->init_reset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593) __raw3270_reset_device(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597) 	/* Check if reset is already pending */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 	if (rp->init_reset.view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600) 	/* Store reset data stream to init_data/init_reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601) 	rp->init_data[0] = TW_KR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602) 	rp->init_reset.ccw.cmd_code = TC_EWRITEA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603) 	rp->init_reset.ccw.flags = CCW_FLAG_SLI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604) 	rp->init_reset.ccw.count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605) 	rp->init_reset.ccw.cda = (__u32) __pa(rp->init_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606) 	rp->init_reset.callback = raw3270_reset_device_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	rc = __raw3270_start(rp, &rp->init_view, &rp->init_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	if (rc == 0 && rp->state == RAW3270_STATE_INIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609) 		rp->state = RAW3270_STATE_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) raw3270_reset_device(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619) 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	rc = __raw3270_reset_device(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) raw3270_reset(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) 	rp = view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 	if (!rp || rp->view != view ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633) 	    test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634) 		rc = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 	else if (!raw3270_state_ready(rp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636) 		rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) 		rc = raw3270_reset_device(view->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643) __raw3270_disconnect(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645) 	struct raw3270_request *rq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646) 	struct raw3270_view *view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648) 	rp->state = RAW3270_STATE_INIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	rp->view = &rp->init_view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	/* Cancel all queued requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	while (!list_empty(&rp->req_queue)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 		rq = list_entry(rp->req_queue.next,struct raw3270_request,list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 		view = rq->view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 		rq->rc = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655) 		list_del_init(&rq->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 		if (rq->callback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657) 			rq->callback(rq, rq->callback_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) 		raw3270_put_view(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) 	/* Start from scratch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 	__raw3270_reset_device(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665) raw3270_init_irq(struct raw3270_view *view, struct raw3270_request *rq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666) 		 struct irb *irb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670) 	if (rq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) 		if (irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 			if (irb->ecw[0] & SNS0_CMD_REJECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) 				rq->rc = -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) 			else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675) 				rq->rc = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 	if (irb->scsw.cmd.dstat & DEV_STAT_ATTENTION) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679) 		/* Queue read modified after attention interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680) 		rp = view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681) 		raw3270_read_modified(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) static struct raw3270_fn raw3270_init_fn = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686) 	.intv = raw3270_init_irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690)  * Setup new 3270 device.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693) raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, char *ascebc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695) 	struct list_head *l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696) 	struct raw3270 *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697) 	int minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	memset(rp, 0, sizeof(struct raw3270));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	/* Copy ebcdic -> ascii translation table. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	memcpy(ascebc, _ascebc, 256);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702) 	if (tubxcorrect) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703) 		/* correct brackets and circumflex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704) 		ascebc['['] = 0xad;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 		ascebc[']'] = 0xbd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 		ascebc['^'] = 0xb0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	rp->ascebc = ascebc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 	/* Set defaults. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	rp->rows = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	rp->cols = 80;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	INIT_LIST_HEAD(&rp->req_queue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	INIT_LIST_HEAD(&rp->view_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717) 	rp->init_view.dev = rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718) 	rp->init_view.fn = &raw3270_init_fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	rp->view = &rp->init_view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	 * Add device to list and find the smallest unused minor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	 * number for it. Note: there is no device with minor 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724) 	 * see special case for fs3270.c:fs3270_open().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726) 	mutex_lock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727) 	/* Keep the list sorted. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	minor = RAW3270_FIRSTMINOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	rp->minor = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	list_for_each(l, &raw3270_devices) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 		tmp = list_entry(l, struct raw3270, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732) 		if (tmp->minor > minor) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 			rp->minor = minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) 			__list_add(&rp->list, l->prev, l);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 		minor++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) 	if (rp->minor == -1 && minor < RAW3270_MAXDEVS + RAW3270_FIRSTMINOR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 		rp->minor = minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		list_add_tail(&rp->list, &raw3270_devices);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 	mutex_unlock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	/* No free minor number? Then give up. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 	if (rp->minor == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 		return -EUSERS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) 	rp->cdev = cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) 	dev_set_drvdata(&cdev->dev, rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 	cdev->handler = raw3270_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) #ifdef CONFIG_TN3270_CONSOLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) /* Tentative definition - see below for actual definition. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755) static struct ccw_driver raw3270_ccw_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758)  * Setup 3270 device configured as console.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) struct raw3270 __init *raw3270_setup_console(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	struct ccw_device *cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	char *ascebc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 	cdev = ccw_device_create_console(&raw3270_ccw_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 	if (IS_ERR(cdev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 		return ERR_CAST(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 	rp = kzalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	ascebc = kzalloc(256, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 	rc = raw3270_setup_device(cdev, rp, ascebc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 		return ERR_PTR(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	set_bit(RAW3270_FLAGS_CONSOLE, &rp->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	rc = ccw_device_enable_console(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 		ccw_device_destroy_console(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782) 		return ERR_PTR(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785) 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 		__raw3270_reset_device(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 		while (!raw3270_state_final(rp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789) 			ccw_device_wait_idle(rp->cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 			barrier();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792) 	} while (rp->state != RAW3270_STATE_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	return rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) raw3270_wait_cons_dev(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802) 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	ccw_device_wait_idle(rp->cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810)  * Create a 3270 device structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) static struct raw3270 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) raw3270_create_device(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 	char *ascebc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 	rp = kzalloc(sizeof(struct raw3270), GFP_KERNEL | GFP_DMA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 	if (!rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 	ascebc = kmalloc(256, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	if (!ascebc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 		kfree(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) 	rc = raw3270_setup_device(cdev, rp, ascebc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 	if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) 		kfree(rp->ascebc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 		kfree(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) 		rp = ERR_PTR(rc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833) 	/* Get reference to ccw_device structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834) 	get_device(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835) 	return rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839)  * Activate a view.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) raw3270_activate_view(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	struct raw3270_view *oldview, *nv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 	rp = view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 	if (!rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 	if (rp->view == view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 		rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 	else if (!raw3270_state_ready(rp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 		rc = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 	else if (test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		rc = -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 	else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 		oldview = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 		if (rp->view && rp->view->fn->deactivate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 			oldview = rp->view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 			oldview->fn->deactivate(oldview);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 		rp->view = view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 		rc = view->fn->activate(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 		if (rc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 			/* Didn't work. Try to reactivate the old view. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 			rp->view = oldview;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870) 			if (!oldview || oldview->fn->activate(oldview) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871) 				/* Didn't work as well. Try any other view. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 				list_for_each_entry(nv, &rp->view_list, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 					if (nv != view && nv != oldview) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874) 						rp->view = nv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875) 						if (nv->fn->activate(nv) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) 							break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 						rp->view = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) 					}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882) 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887)  * Deactivate current view.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890) raw3270_deactivate_view(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895) 	rp = view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	if (!rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	if (rp->view == view) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900) 		view->fn->deactivate(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901) 		rp->view = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902) 		/* Move deactivated view to end of list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903) 		list_del_init(&view->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 		list_add_tail(&view->list, &rp->view_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905) 		/* Try to activate another view. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 		if (raw3270_state_ready(rp) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 		    !test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 			list_for_each_entry(view, &rp->view_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 				rp->view = view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 				if (view->fn->activate(view) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 				rp->view = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916) 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920)  * Add view to device with minor "minor".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) raw3270_add_view(struct raw3270_view *view, struct raw3270_fn *fn, int minor, int subclass)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	if (minor <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930) 		return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931) 	mutex_lock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932) 	rc = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933) 	list_for_each_entry(rp, &raw3270_devices, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934) 		if (rp->minor != minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936) 		spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937) 		atomic_set(&view->ref_count, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938) 		view->dev = rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939) 		view->fn = fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940) 		view->model = rp->model;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941) 		view->rows = rp->rows;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942) 		view->cols = rp->cols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943) 		view->ascebc = rp->ascebc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 		spin_lock_init(&view->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945) 		lockdep_set_subclass(&view->lock, subclass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 		list_add(&view->list, &rp->view_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 		rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	mutex_unlock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956)  * Find specific view of device with minor "minor".
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) struct raw3270_view *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) raw3270_find_view(struct raw3270_fn *fn, int minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	struct raw3270_view *view, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	mutex_lock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 	view = ERR_PTR(-ENODEV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	list_for_each_entry(rp, &raw3270_devices, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 		if (rp->minor != minor)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 		spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 		list_for_each_entry(tmp, &rp->view_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 			if (tmp->fn == fn) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 				raw3270_get_view(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 				view = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 		spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	mutex_unlock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	return view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986)  * Remove view from device and free view structure via call to view->fn->free.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) raw3270_del_view(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	struct raw3270_view *nv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	rp = view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	if (rp->view == view) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 		view->fn->deactivate(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 		rp->view = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	list_del_init(&view->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) 	if (!rp->view && raw3270_state_ready(rp) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) 	    !test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) 		/* Try to activate another view. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 		list_for_each_entry(nv, &rp->view_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 			if (nv->fn->activate(nv) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) 				rp->view = nv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) 				break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) 	/* Wait for reference counter to drop to zero. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) 	atomic_dec(&view->ref_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) 	wait_event(raw3270_wait_queue, atomic_read(&view->ref_count) == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) 	if (view->fn->free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) 		view->fn->free(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)  * Remove a 3270 device structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) raw3270_delete_device(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) 	struct ccw_device *cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) 	/* Remove from device chain. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 	mutex_lock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) 	list_del_init(&rp->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 	mutex_unlock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) 	/* Disconnect from ccw_device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) 	cdev = rp->cdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) 	rp->cdev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) 	dev_set_drvdata(&cdev->dev, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	cdev->handler = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) 	/* Put ccw_device structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) 	put_device(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) 	/* Now free raw3270 structure. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) 	kfree(rp->ascebc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 	kfree(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) raw3270_probe (struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)  * Additional attributes for a 3270 device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) raw3270_model_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) 	return snprintf(buf, PAGE_SIZE, "%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 			((struct raw3270 *) dev_get_drvdata(dev))->model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) static DEVICE_ATTR(model, 0444, raw3270_model_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) raw3270_rows_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 	return snprintf(buf, PAGE_SIZE, "%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 			((struct raw3270 *) dev_get_drvdata(dev))->rows);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) static DEVICE_ATTR(rows, 0444, raw3270_rows_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) raw3270_columns_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) 	return snprintf(buf, PAGE_SIZE, "%i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 			((struct raw3270 *) dev_get_drvdata(dev))->cols);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) static DEVICE_ATTR(columns, 0444, raw3270_columns_show, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) static struct attribute * raw3270_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) 	&dev_attr_model.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) 	&dev_attr_rows.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) 	&dev_attr_columns.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) 	NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) static const struct attribute_group raw3270_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) 	.attrs = raw3270_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) static int raw3270_create_attributes(struct raw3270 *rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) 	return sysfs_create_group(&rp->cdev->dev.kobj, &raw3270_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)  * Notifier for device addition/removal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) static LIST_HEAD(raw3270_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) int raw3270_register_notifier(struct raw3270_notifier *notifier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) 	mutex_lock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) 	list_add_tail(&notifier->list, &raw3270_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 	list_for_each_entry(rp, &raw3270_devices, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) 		notifier->create(rp->minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) 	mutex_unlock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) void raw3270_unregister_notifier(struct raw3270_notifier *notifier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) 	mutex_lock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	list_for_each_entry(rp, &raw3270_devices, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 		notifier->destroy(rp->minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 	list_del(&notifier->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) 	mutex_unlock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125)  * Set 3270 device online.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) raw3270_set_online (struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 	struct raw3270_notifier *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	rp = raw3270_create_device(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 	if (IS_ERR(rp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 		return PTR_ERR(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 	rc = raw3270_create_attributes(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 		goto failure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	raw3270_reset_device(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 	mutex_lock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 	list_for_each_entry(np, &raw3270_notifier, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 		np->create(rp->minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) 	mutex_unlock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) failure:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) 	raw3270_delete_device(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)  * Remove 3270 device structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) raw3270_remove (struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 	struct raw3270_view *v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) 	struct raw3270_notifier *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 	rp = dev_get_drvdata(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) 	 * _remove is the opposite of _probe; it's probe that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	 * should set up rp.  raw3270_remove gets entered for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 	 * devices even if they haven't been varied online.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	 * Thus, rp may validly be NULL here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 	if (rp == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	sysfs_remove_group(&cdev->dev.kobj, &raw3270_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 	/* Deactivate current view and remove all views. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) 	spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) 	if (rp->view) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 		if (rp->view->fn->deactivate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 			rp->view->fn->deactivate(rp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 		rp->view = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 	while (!list_empty(&rp->view_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 		v = list_entry(rp->view_list.next, struct raw3270_view, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) 		if (v->fn->release)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 			v->fn->release(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) 		spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) 		raw3270_del_view(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 		spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 	spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	mutex_lock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) 	list_for_each_entry(np, &raw3270_notifier, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 		np->destroy(rp->minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) 	mutex_unlock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	/* Reset 3270 device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	raw3270_reset_device(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 	/* And finally remove it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 	raw3270_delete_device(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)  * Set 3270 device offline.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) raw3270_set_offline (struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 	rp = dev_get_drvdata(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 	if (test_bit(RAW3270_FLAGS_CONSOLE, &rp->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	raw3270_remove(cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) static int raw3270_pm_stop(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 	struct raw3270_view *view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	rp = dev_get_drvdata(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	if (!rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	if (rp->view && rp->view->fn->deactivate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) 		rp->view->fn->deactivate(rp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 	if (!test_bit(RAW3270_FLAGS_CONSOLE, &rp->flags)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 		 * Release tty and fullscreen for all non-console
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) 		 * devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 		list_for_each_entry(view, &rp->view_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 			if (view->fn->release)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) 				view->fn->release(view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 	set_bit(RAW3270_FLAGS_FROZEN, &rp->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) static int raw3270_pm_start(struct ccw_device *cdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) 	rp = dev_get_drvdata(&cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 	if (!rp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 	spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) 	clear_bit(RAW3270_FLAGS_FROZEN, &rp->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 	if (rp->view && rp->view->fn->activate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 		rp->view->fn->activate(rp->view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) 	spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) void raw3270_pm_unfreeze(struct raw3270_view *view)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) #ifdef CONFIG_TN3270_CONSOLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	rp = view->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 	if (rp && test_bit(RAW3270_FLAGS_FROZEN, &rp->flags))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 		ccw_device_force_console(rp->cdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) static struct ccw_device_id raw3270_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 	{ CCW_DEVICE(0x3270, 0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 	{ CCW_DEVICE(0x3271, 0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) 	{ CCW_DEVICE(0x3272, 0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	{ CCW_DEVICE(0x3273, 0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 	{ CCW_DEVICE(0x3274, 0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) 	{ CCW_DEVICE(0x3275, 0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) 	{ CCW_DEVICE(0x3276, 0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	{ CCW_DEVICE(0x3277, 0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 	{ CCW_DEVICE(0x3278, 0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 	{ CCW_DEVICE(0x3279, 0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 	{ CCW_DEVICE(0x3174, 0) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 	{ /* end of list */ },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) static struct ccw_driver raw3270_ccw_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 		.name	= "3270",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) 		.owner	= THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 	.ids		= raw3270_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) 	.probe		= &raw3270_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 	.remove		= &raw3270_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) 	.set_online	= &raw3270_set_online,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) 	.set_offline	= &raw3270_set_offline,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) 	.freeze		= &raw3270_pm_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) 	.thaw		= &raw3270_pm_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) 	.restore	= &raw3270_pm_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	.int_class	= IRQIO_C70,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) raw3270_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) 	struct raw3270 *rp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 	if (raw3270_registered)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) 	raw3270_registered = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) 	rc = ccw_driver_register(&raw3270_ccw_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) 	if (rc == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) 		/* Create attributes for early (= console) device. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) 		mutex_lock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 		class3270 = class_create(THIS_MODULE, "3270");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) 		list_for_each_entry(rp, &raw3270_devices, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) 			get_device(&rp->cdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) 			raw3270_create_attributes(rp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 		mutex_unlock(&raw3270_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 	return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) raw3270_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 	ccw_driver_unregister(&raw3270_ccw_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) 	class_destroy(class3270);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) module_init(raw3270_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) module_exit(raw3270_exit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) EXPORT_SYMBOL(class3270);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) EXPORT_SYMBOL(raw3270_request_alloc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) EXPORT_SYMBOL(raw3270_request_free);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) EXPORT_SYMBOL(raw3270_request_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) EXPORT_SYMBOL(raw3270_request_set_cmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) EXPORT_SYMBOL(raw3270_request_add_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) EXPORT_SYMBOL(raw3270_request_set_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) EXPORT_SYMBOL(raw3270_request_set_idal);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) EXPORT_SYMBOL(raw3270_buffer_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) EXPORT_SYMBOL(raw3270_add_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) EXPORT_SYMBOL(raw3270_del_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) EXPORT_SYMBOL(raw3270_find_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) EXPORT_SYMBOL(raw3270_activate_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) EXPORT_SYMBOL(raw3270_deactivate_view);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) EXPORT_SYMBOL(raw3270_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) EXPORT_SYMBOL(raw3270_start_locked);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) EXPORT_SYMBOL(raw3270_start_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) EXPORT_SYMBOL(raw3270_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) EXPORT_SYMBOL(raw3270_register_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) EXPORT_SYMBOL(raw3270_unregister_notifier);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) EXPORT_SYMBOL(raw3270_wait_queue);