Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * IBM/3270 Driver
0004  *
0005  * Author(s):
0006  *   Original 3270 Code for 2.4 written by Richard Hitt (UTS Global)
0007  *   Rewritten for 2.5 by Martin Schwidefsky <schwidefsky@de.ibm.com>
0008  *     Copyright IBM Corp. 2003, 2009
0009  */
0010 
0011 #include <asm/idals.h>
0012 #include <asm/ioctl.h>
0013 
0014 /* ioctls for fullscreen 3270 */
0015 #define TUBICMD     _IO('3', 3) /* set ccw command for fs reads. */
0016 #define TUBOCMD     _IO('3', 4) /* set ccw command for fs writes. */
0017 #define TUBGETI     _IO('3', 7) /* get ccw command for fs reads. */
0018 #define TUBGETO     _IO('3', 8) /* get ccw command for fs writes. */
0019 #define TUBSETMOD   _IO('3',12) /* FIXME: what does it do ?*/
0020 #define TUBGETMOD   _IO('3',13) /* FIXME: what does it do ?*/
0021 
0022 /* Local Channel Commands */
0023 #define TC_WRITE    0x01        /* Write */
0024 #define TC_RDBUF    0x02        /* Read Buffer */
0025 #define TC_EWRITE   0x05        /* Erase write */
0026 #define TC_READMOD  0x06        /* Read modified */
0027 #define TC_EWRITEA  0x0d        /* Erase write alternate */
0028 #define TC_WRITESF  0x11        /* Write structured field */
0029 
0030 /* Buffer Control Orders */
0031 #define TO_SF       0x1d        /* Start field */
0032 #define TO_SBA      0x11        /* Set buffer address */
0033 #define TO_IC       0x13        /* Insert cursor */
0034 #define TO_PT       0x05        /* Program tab */
0035 #define TO_RA       0x3c        /* Repeat to address */
0036 #define TO_SFE      0x29        /* Start field extended */
0037 #define TO_EUA      0x12        /* Erase unprotected to address */
0038 #define TO_MF       0x2c        /* Modify field */
0039 #define TO_SA       0x28        /* Set attribute */
0040 
0041 /* Field Attribute Bytes */
0042 #define TF_INPUT    0x40        /* Visible input */
0043 #define TF_INPUTN   0x4c        /* Invisible input */
0044 #define TF_INMDT    0xc1        /* Visible, Set-MDT */
0045 #define TF_LOG      0x60
0046 
0047 /* Character Attribute Bytes */
0048 #define TAT_RESET   0x00
0049 #define TAT_FIELD   0xc0
0050 #define TAT_EXTHI   0x41
0051 #define TAT_COLOR   0x42
0052 #define TAT_CHARS   0x43
0053 #define TAT_TRANS   0x46
0054 
0055 /* Extended-Highlighting Bytes */
0056 #define TAX_RESET   0x00
0057 #define TAX_BLINK   0xf1
0058 #define TAX_REVER   0xf2
0059 #define TAX_UNDER   0xf4
0060 
0061 /* Reset value */
0062 #define TAR_RESET   0x00
0063 
0064 /* Color values */
0065 #define TAC_RESET   0x00
0066 #define TAC_BLUE    0xf1
0067 #define TAC_RED     0xf2
0068 #define TAC_PINK    0xf3
0069 #define TAC_GREEN   0xf4
0070 #define TAC_TURQ    0xf5
0071 #define TAC_YELLOW  0xf6
0072 #define TAC_WHITE   0xf7
0073 #define TAC_DEFAULT 0x00
0074 
0075 /* Write Control Characters */
0076 #define TW_NONE     0x40        /* No particular action */
0077 #define TW_KR       0xc2        /* Keyboard restore */
0078 #define TW_PLUSALARM    0x04        /* Add this bit for alarm */
0079 
0080 #define RAW3270_FIRSTMINOR  1   /* First minor number */
0081 #define RAW3270_MAXDEVS     255 /* Max number of 3270 devices */
0082 
0083 /* For TUBGETMOD and TUBSETMOD. Should include. */
0084 struct raw3270_iocb {
0085     short model;
0086     short line_cnt;
0087     short col_cnt;
0088     short pf_cnt;
0089     short re_cnt;
0090     short map;
0091 };
0092 
0093 struct raw3270;
0094 struct raw3270_view;
0095 extern struct class *class3270;
0096 
0097 /* 3270 CCW request */
0098 struct raw3270_request {
0099     struct list_head list;      /* list head for request queueing. */
0100     struct raw3270_view *view;  /* view of this request */
0101     struct ccw1 ccw;        /* single ccw. */
0102     void *buffer;           /* output buffer. */
0103     size_t size;            /* size of output buffer. */
0104     int rescnt;         /* residual count from devstat. */
0105     int rc;             /* return code for this request. */
0106 
0107     /* Callback for delivering final status. */
0108     void (*callback)(struct raw3270_request *, void *);
0109     void *callback_data;
0110 };
0111 
0112 struct raw3270_request *raw3270_request_alloc(size_t size);
0113 void raw3270_request_free(struct raw3270_request *);
0114 void raw3270_request_reset(struct raw3270_request *);
0115 void raw3270_request_set_cmd(struct raw3270_request *, u8 cmd);
0116 int  raw3270_request_add_data(struct raw3270_request *, void *, size_t);
0117 void raw3270_request_set_data(struct raw3270_request *, void *, size_t);
0118 void raw3270_request_set_idal(struct raw3270_request *, struct idal_buffer *);
0119 
0120 static inline int
0121 raw3270_request_final(struct raw3270_request *rq)
0122 {
0123     return list_empty(&rq->list);
0124 }
0125 
0126 void raw3270_buffer_address(struct raw3270 *, char *, unsigned short);
0127 
0128 /*
0129  * Functions of a 3270 view.
0130  */
0131 struct raw3270_fn {
0132     int  (*activate)(struct raw3270_view *);
0133     void (*deactivate)(struct raw3270_view *);
0134     void (*intv)(struct raw3270_view *,
0135              struct raw3270_request *, struct irb *);
0136     void (*release)(struct raw3270_view *);
0137     void (*free)(struct raw3270_view *);
0138     void (*resize)(struct raw3270_view *, int, int, int);
0139 };
0140 
0141 /*
0142  * View structure chaining. The raw3270_view structure is meant to
0143  * be embedded at the start of the real view data structure, e.g.:
0144  *   struct example {
0145  *     struct raw3270_view view;
0146  *     ...
0147  *   };
0148  */
0149 struct raw3270_view {
0150     struct list_head list;
0151     spinlock_t lock;
0152 #define RAW3270_VIEW_LOCK_IRQ   0
0153 #define RAW3270_VIEW_LOCK_BH    1
0154     atomic_t ref_count;
0155     struct raw3270 *dev;
0156     struct raw3270_fn *fn;
0157     unsigned int model;
0158     unsigned int rows, cols;    /* # of rows & colums of the view */
0159     unsigned char *ascebc;      /* ascii -> ebcdic table */
0160 };
0161 
0162 int raw3270_add_view(struct raw3270_view *, struct raw3270_fn *, int, int);
0163 int raw3270_view_lock_unavailable(struct raw3270_view *view);
0164 int raw3270_activate_view(struct raw3270_view *);
0165 void raw3270_del_view(struct raw3270_view *);
0166 void raw3270_deactivate_view(struct raw3270_view *);
0167 struct raw3270_view *raw3270_find_view(struct raw3270_fn *, int);
0168 int raw3270_start(struct raw3270_view *, struct raw3270_request *);
0169 int raw3270_start_locked(struct raw3270_view *, struct raw3270_request *);
0170 int raw3270_start_irq(struct raw3270_view *, struct raw3270_request *);
0171 int raw3270_reset(struct raw3270_view *);
0172 struct raw3270_view *raw3270_view(struct raw3270_view *);
0173 int raw3270_view_active(struct raw3270_view *);
0174 
0175 /* Reference count inliner for view structures. */
0176 static inline void
0177 raw3270_get_view(struct raw3270_view *view)
0178 {
0179     atomic_inc(&view->ref_count);
0180 }
0181 
0182 extern wait_queue_head_t raw3270_wait_queue;
0183 
0184 static inline void
0185 raw3270_put_view(struct raw3270_view *view)
0186 {
0187     if (atomic_dec_return(&view->ref_count) == 0)
0188         wake_up(&raw3270_wait_queue);
0189 }
0190 
0191 struct raw3270 *raw3270_setup_console(void);
0192 void raw3270_wait_cons_dev(struct raw3270 *);
0193 
0194 /* Notifier for device addition/removal */
0195 struct raw3270_notifier {
0196     struct list_head list;
0197     void (*create)(int minor);
0198     void (*destroy)(int minor);
0199 };
0200 
0201 int raw3270_register_notifier(struct raw3270_notifier *);
0202 void raw3270_unregister_notifier(struct raw3270_notifier *);
0203 
0204 /*
0205  * Little memory allocator for string objects. 
0206  */
0207 struct string
0208 {
0209     struct list_head list;
0210     struct list_head update;
0211     unsigned long size;
0212     unsigned long len;
0213     char string[];
0214 } __attribute__ ((aligned(8)));
0215 
0216 static inline struct string *
0217 alloc_string(struct list_head *free_list, unsigned long len)
0218 {
0219     struct string *cs, *tmp;
0220     unsigned long size;
0221 
0222     size = (len + 7L) & -8L;
0223     list_for_each_entry(cs, free_list, list) {
0224         if (cs->size < size)
0225             continue;
0226         if (cs->size > size + sizeof(struct string)) {
0227             char *endaddr = (char *) (cs + 1) + cs->size;
0228             tmp = (struct string *) (endaddr - size) - 1;
0229             tmp->size = size;
0230             cs->size -= size + sizeof(struct string);
0231             cs = tmp;
0232         } else
0233             list_del(&cs->list);
0234         cs->len = len;
0235         INIT_LIST_HEAD(&cs->list);
0236         INIT_LIST_HEAD(&cs->update);
0237         return cs;
0238     }
0239     return NULL;
0240 }
0241 
0242 static inline unsigned long
0243 free_string(struct list_head *free_list, struct string *cs)
0244 {
0245     struct string *tmp;
0246     struct list_head *p, *left;
0247 
0248     /* Find out the left neighbour in free memory list. */
0249     left = free_list;
0250     list_for_each(p, free_list) {
0251         if (list_entry(p, struct string, list) > cs)
0252             break;
0253         left = p;
0254     }
0255     /* Try to merge with right neighbour = next element from left. */
0256     if (left->next != free_list) {
0257         tmp = list_entry(left->next, struct string, list);
0258         if ((char *) (cs + 1) + cs->size == (char *) tmp) {
0259             list_del(&tmp->list);
0260             cs->size += tmp->size + sizeof(struct string);
0261         }
0262     }
0263     /* Try to merge with left neighbour. */
0264     if (left != free_list) {
0265         tmp = list_entry(left, struct string, list);
0266         if ((char *) (tmp + 1) + tmp->size == (char *) cs) {
0267             tmp->size += cs->size + sizeof(struct string);
0268             return tmp->size;
0269         }
0270     }
0271     __list_add(&cs->list, left, left->next);
0272     return cs->size;
0273 }
0274 
0275 static inline void
0276 add_string_memory(struct list_head *free_list, void *mem, unsigned long size)
0277 {
0278     struct string *cs;
0279 
0280     cs = (struct string *) mem;
0281     cs->size = size - sizeof(struct string);
0282     free_string(free_list, cs);
0283 }
0284