^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(¬ifier->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(¬ifier->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);