Commit 30c2df51173ea4e4755ad52be7f2914f01e32404

Authored by Martin Schwidefsky
1 parent fca894edd7

[S390] sclp: event buffer dissection

Move gds vector/subvector find functions to the sclp header file.
Simplify event buffer dissection in sclp tty code.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

Showing 2 changed files with 60 additions and 84 deletions Inline Diff

drivers/s390/char/sclp.h
1 /* 1 /*
2 * Copyright IBM Corp. 1999, 2009 2 * Copyright IBM Corp. 1999, 2009
3 * 3 *
4 * Author(s): Martin Peschke <mpeschke@de.ibm.com> 4 * Author(s): Martin Peschke <mpeschke@de.ibm.com>
5 * Martin Schwidefsky <schwidefsky@de.ibm.com> 5 * Martin Schwidefsky <schwidefsky@de.ibm.com>
6 */ 6 */
7 7
8 #ifndef __SCLP_H__ 8 #ifndef __SCLP_H__
9 #define __SCLP_H__ 9 #define __SCLP_H__
10 10
11 #include <linux/types.h> 11 #include <linux/types.h>
12 #include <linux/list.h> 12 #include <linux/list.h>
13 #include <asm/sclp.h> 13 #include <asm/sclp.h>
14 #include <asm/ebcdic.h> 14 #include <asm/ebcdic.h>
15 15
16 /* maximum number of pages concerning our own memory management */ 16 /* maximum number of pages concerning our own memory management */
17 #define MAX_KMEM_PAGES (sizeof(unsigned long) << 3) 17 #define MAX_KMEM_PAGES (sizeof(unsigned long) << 3)
18 #define MAX_CONSOLE_PAGES 6 18 #define MAX_CONSOLE_PAGES 6
19 19
20 #define EVTYP_OPCMD 0x01 20 #define EVTYP_OPCMD 0x01
21 #define EVTYP_MSG 0x02 21 #define EVTYP_MSG 0x02
22 #define EVTYP_STATECHANGE 0x08 22 #define EVTYP_STATECHANGE 0x08
23 #define EVTYP_PMSGCMD 0x09 23 #define EVTYP_PMSGCMD 0x09
24 #define EVTYP_CNTLPROGOPCMD 0x20 24 #define EVTYP_CNTLPROGOPCMD 0x20
25 #define EVTYP_CNTLPROGIDENT 0x0B 25 #define EVTYP_CNTLPROGIDENT 0x0B
26 #define EVTYP_SIGQUIESCE 0x1D 26 #define EVTYP_SIGQUIESCE 0x1D
27 #define EVTYP_VT220MSG 0x1A 27 #define EVTYP_VT220MSG 0x1A
28 #define EVTYP_CONFMGMDATA 0x04 28 #define EVTYP_CONFMGMDATA 0x04
29 #define EVTYP_SDIAS 0x1C 29 #define EVTYP_SDIAS 0x1C
30 #define EVTYP_ASYNC 0x0A 30 #define EVTYP_ASYNC 0x0A
31 31
32 #define EVTYP_OPCMD_MASK 0x80000000 32 #define EVTYP_OPCMD_MASK 0x80000000
33 #define EVTYP_MSG_MASK 0x40000000 33 #define EVTYP_MSG_MASK 0x40000000
34 #define EVTYP_STATECHANGE_MASK 0x01000000 34 #define EVTYP_STATECHANGE_MASK 0x01000000
35 #define EVTYP_PMSGCMD_MASK 0x00800000 35 #define EVTYP_PMSGCMD_MASK 0x00800000
36 #define EVTYP_CTLPROGOPCMD_MASK 0x00000001 36 #define EVTYP_CTLPROGOPCMD_MASK 0x00000001
37 #define EVTYP_CTLPROGIDENT_MASK 0x00200000 37 #define EVTYP_CTLPROGIDENT_MASK 0x00200000
38 #define EVTYP_SIGQUIESCE_MASK 0x00000008 38 #define EVTYP_SIGQUIESCE_MASK 0x00000008
39 #define EVTYP_VT220MSG_MASK 0x00000040 39 #define EVTYP_VT220MSG_MASK 0x00000040
40 #define EVTYP_CONFMGMDATA_MASK 0x10000000 40 #define EVTYP_CONFMGMDATA_MASK 0x10000000
41 #define EVTYP_SDIAS_MASK 0x00000010 41 #define EVTYP_SDIAS_MASK 0x00000010
42 #define EVTYP_ASYNC_MASK 0x00400000 42 #define EVTYP_ASYNC_MASK 0x00400000
43 43
44 #define GNRLMSGFLGS_DOM 0x8000 44 #define GNRLMSGFLGS_DOM 0x8000
45 #define GNRLMSGFLGS_SNDALRM 0x4000 45 #define GNRLMSGFLGS_SNDALRM 0x4000
46 #define GNRLMSGFLGS_HOLDMSG 0x2000 46 #define GNRLMSGFLGS_HOLDMSG 0x2000
47 47
48 #define LNTPFLGS_CNTLTEXT 0x8000 48 #define LNTPFLGS_CNTLTEXT 0x8000
49 #define LNTPFLGS_LABELTEXT 0x4000 49 #define LNTPFLGS_LABELTEXT 0x4000
50 #define LNTPFLGS_DATATEXT 0x2000 50 #define LNTPFLGS_DATATEXT 0x2000
51 #define LNTPFLGS_ENDTEXT 0x1000 51 #define LNTPFLGS_ENDTEXT 0x1000
52 #define LNTPFLGS_PROMPTTEXT 0x0800 52 #define LNTPFLGS_PROMPTTEXT 0x0800
53 53
54 typedef unsigned int sclp_cmdw_t; 54 typedef unsigned int sclp_cmdw_t;
55 55
56 #define SCLP_CMDW_READ_EVENT_DATA 0x00770005 56 #define SCLP_CMDW_READ_EVENT_DATA 0x00770005
57 #define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005 57 #define SCLP_CMDW_WRITE_EVENT_DATA 0x00760005
58 #define SCLP_CMDW_WRITE_EVENT_MASK 0x00780005 58 #define SCLP_CMDW_WRITE_EVENT_MASK 0x00780005
59 59
60 #define GDS_ID_MDSMU 0x1310 60 #define GDS_ID_MDSMU 0x1310
61 #define GDS_ID_MDSROUTEINFO 0x1311 61 #define GDS_ID_MDSROUTEINFO 0x1311
62 #define GDS_ID_AGUNWRKCORR 0x1549 62 #define GDS_ID_AGUNWRKCORR 0x1549
63 #define GDS_ID_SNACONDREPORT 0x1532 63 #define GDS_ID_SNACONDREPORT 0x1532
64 #define GDS_ID_CPMSU 0x1212 64 #define GDS_ID_CPMSU 0x1212
65 #define GDS_ID_ROUTTARGINSTR 0x154D 65 #define GDS_ID_ROUTTARGINSTR 0x154D
66 #define GDS_ID_OPREQ 0x8070 66 #define GDS_ID_OPREQ 0x8070
67 #define GDS_ID_TEXTCMD 0x1320 67 #define GDS_ID_TEXTCMD 0x1320
68 68
69 #define GDS_KEY_SELFDEFTEXTMSG 0x31 69 #define GDS_KEY_SELFDEFTEXTMSG 0x31
70 70
71 enum sclp_pm_event { 71 enum sclp_pm_event {
72 SCLP_PM_EVENT_FREEZE, 72 SCLP_PM_EVENT_FREEZE,
73 SCLP_PM_EVENT_THAW, 73 SCLP_PM_EVENT_THAW,
74 SCLP_PM_EVENT_RESTORE, 74 SCLP_PM_EVENT_RESTORE,
75 }; 75 };
76 76
77 #define SCLP_PANIC_PRIO 1 77 #define SCLP_PANIC_PRIO 1
78 #define SCLP_PANIC_PRIO_CLIENT 0 78 #define SCLP_PANIC_PRIO_CLIENT 0
79 79
80 typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */ 80 typedef u32 sccb_mask_t; /* ATTENTION: assumes 32bit mask !!! */
81 81
82 struct sccb_header { 82 struct sccb_header {
83 u16 length; 83 u16 length;
84 u8 function_code; 84 u8 function_code;
85 u8 control_mask[3]; 85 u8 control_mask[3];
86 u16 response_code; 86 u16 response_code;
87 } __attribute__((packed)); 87 } __attribute__((packed));
88 88
89 extern u64 sclp_facilities; 89 extern u64 sclp_facilities;
90 #define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) 90 #define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL)
91 #define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) 91 #define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL)
92 #define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL) 92 #define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL)
93 #define SCLP_HAS_CPU_RECONFIG (sclp_facilities & 0x0400000000000000ULL) 93 #define SCLP_HAS_CPU_RECONFIG (sclp_facilities & 0x0400000000000000ULL)
94 94
95 95
96 struct gds_subvector { 96 struct gds_subvector {
97 u8 length; 97 u8 length;
98 u8 key; 98 u8 key;
99 } __attribute__((packed)); 99 } __attribute__((packed));
100 100
101 struct gds_vector { 101 struct gds_vector {
102 u16 length; 102 u16 length;
103 u16 gds_id; 103 u16 gds_id;
104 } __attribute__((packed)); 104 } __attribute__((packed));
105 105
106 struct evbuf_header { 106 struct evbuf_header {
107 u16 length; 107 u16 length;
108 u8 type; 108 u8 type;
109 u8 flags; 109 u8 flags;
110 u16 _reserved; 110 u16 _reserved;
111 } __attribute__((packed)); 111 } __attribute__((packed));
112 112
113 struct sclp_req { 113 struct sclp_req {
114 struct list_head list; /* list_head for request queueing. */ 114 struct list_head list; /* list_head for request queueing. */
115 sclp_cmdw_t command; /* sclp command to execute */ 115 sclp_cmdw_t command; /* sclp command to execute */
116 void *sccb; /* pointer to the sccb to execute */ 116 void *sccb; /* pointer to the sccb to execute */
117 char status; /* status of this request */ 117 char status; /* status of this request */
118 int start_count; /* number of SVCs done for this req */ 118 int start_count; /* number of SVCs done for this req */
119 /* Callback that is called after reaching final status. */ 119 /* Callback that is called after reaching final status. */
120 void (*callback)(struct sclp_req *, void *data); 120 void (*callback)(struct sclp_req *, void *data);
121 void *callback_data; 121 void *callback_data;
122 }; 122 };
123 123
124 #define SCLP_REQ_FILLED 0x00 /* request is ready to be processed */ 124 #define SCLP_REQ_FILLED 0x00 /* request is ready to be processed */
125 #define SCLP_REQ_QUEUED 0x01 /* request is queued to be processed */ 125 #define SCLP_REQ_QUEUED 0x01 /* request is queued to be processed */
126 #define SCLP_REQ_RUNNING 0x02 /* request is currently running */ 126 #define SCLP_REQ_RUNNING 0x02 /* request is currently running */
127 #define SCLP_REQ_DONE 0x03 /* request is completed successfully */ 127 #define SCLP_REQ_DONE 0x03 /* request is completed successfully */
128 #define SCLP_REQ_FAILED 0x05 /* request is finally failed */ 128 #define SCLP_REQ_FAILED 0x05 /* request is finally failed */
129 129
130 /* function pointers that a high level driver has to use for registration */ 130 /* function pointers that a high level driver has to use for registration */
131 /* of some routines it wants to be called from the low level driver */ 131 /* of some routines it wants to be called from the low level driver */
132 struct sclp_register { 132 struct sclp_register {
133 struct list_head list; 133 struct list_head list;
134 /* User wants to receive: */ 134 /* User wants to receive: */
135 sccb_mask_t receive_mask; 135 sccb_mask_t receive_mask;
136 /* User wants to send: */ 136 /* User wants to send: */
137 sccb_mask_t send_mask; 137 sccb_mask_t send_mask;
138 /* H/W can receive: */ 138 /* H/W can receive: */
139 sccb_mask_t sclp_receive_mask; 139 sccb_mask_t sclp_receive_mask;
140 /* H/W can send: */ 140 /* H/W can send: */
141 sccb_mask_t sclp_send_mask; 141 sccb_mask_t sclp_send_mask;
142 /* called if event type availability changes */ 142 /* called if event type availability changes */
143 void (*state_change_fn)(struct sclp_register *); 143 void (*state_change_fn)(struct sclp_register *);
144 /* called for events in cp_receive_mask/sclp_receive_mask */ 144 /* called for events in cp_receive_mask/sclp_receive_mask */
145 void (*receiver_fn)(struct evbuf_header *); 145 void (*receiver_fn)(struct evbuf_header *);
146 /* called for power management events */ 146 /* called for power management events */
147 void (*pm_event_fn)(struct sclp_register *, enum sclp_pm_event); 147 void (*pm_event_fn)(struct sclp_register *, enum sclp_pm_event);
148 /* pm event posted flag */ 148 /* pm event posted flag */
149 int pm_event_posted; 149 int pm_event_posted;
150 }; 150 };
151 151
152 /* externals from sclp.c */ 152 /* externals from sclp.c */
153 int sclp_add_request(struct sclp_req *req); 153 int sclp_add_request(struct sclp_req *req);
154 void sclp_sync_wait(void); 154 void sclp_sync_wait(void);
155 int sclp_register(struct sclp_register *reg); 155 int sclp_register(struct sclp_register *reg);
156 void sclp_unregister(struct sclp_register *reg); 156 void sclp_unregister(struct sclp_register *reg);
157 int sclp_remove_processed(struct sccb_header *sccb); 157 int sclp_remove_processed(struct sccb_header *sccb);
158 int sclp_deactivate(void); 158 int sclp_deactivate(void);
159 int sclp_reactivate(void); 159 int sclp_reactivate(void);
160 int sclp_service_call(sclp_cmdw_t command, void *sccb); 160 int sclp_service_call(sclp_cmdw_t command, void *sccb);
161 161
162 int sclp_sdias_init(void); 162 int sclp_sdias_init(void);
163 void sclp_sdias_exit(void); 163 void sclp_sdias_exit(void);
164 164
165 /* useful inlines */ 165 /* useful inlines */
166 166
167 /* VM uses EBCDIC 037, LPAR+native(SE+HMC) use EBCDIC 500 */ 167 /* VM uses EBCDIC 037, LPAR+native(SE+HMC) use EBCDIC 500 */
168 /* translate single character from ASCII to EBCDIC */ 168 /* translate single character from ASCII to EBCDIC */
169 static inline unsigned char 169 static inline unsigned char
170 sclp_ascebc(unsigned char ch) 170 sclp_ascebc(unsigned char ch)
171 { 171 {
172 return (MACHINE_IS_VM) ? _ascebc[ch] : _ascebc_500[ch]; 172 return (MACHINE_IS_VM) ? _ascebc[ch] : _ascebc_500[ch];
173 } 173 }
174 174
175 /* translate string from EBCDIC to ASCII */ 175 /* translate string from EBCDIC to ASCII */
176 static inline void 176 static inline void
177 sclp_ebcasc_str(unsigned char *str, int nr) 177 sclp_ebcasc_str(unsigned char *str, int nr)
178 { 178 {
179 (MACHINE_IS_VM) ? EBCASC(str, nr) : EBCASC_500(str, nr); 179 (MACHINE_IS_VM) ? EBCASC(str, nr) : EBCASC_500(str, nr);
180 } 180 }
181 181
182 /* translate string from ASCII to EBCDIC */ 182 /* translate string from ASCII to EBCDIC */
183 static inline void 183 static inline void
184 sclp_ascebc_str(unsigned char *str, int nr) 184 sclp_ascebc_str(unsigned char *str, int nr)
185 { 185 {
186 (MACHINE_IS_VM) ? ASCEBC(str, nr) : ASCEBC_500(str, nr); 186 (MACHINE_IS_VM) ? ASCEBC(str, nr) : ASCEBC_500(str, nr);
187 } 187 }
188 188
189 static inline struct gds_vector *
190 sclp_find_gds_vector(void *start, void *end, u16 id)
191 {
192 struct gds_vector *v;
193
194 for (v = start; (void *) v < end; v = (void *) v + v->length)
195 if (v->gds_id == id)
196 return v;
197 return NULL;
198 }
199
200 static inline struct gds_subvector *
201 sclp_find_gds_subvector(void *start, void *end, u8 key)
202 {
203 struct gds_subvector *sv;
204
205 for (sv = start; (void *) sv < end; sv = (void *) sv + sv->length)
206 if (sv->key == key)
207 return sv;
208 return NULL;
209 }
210
189 #endif /* __SCLP_H__ */ 211 #endif /* __SCLP_H__ */
190 212
drivers/s390/char/sclp_tty.c
1 /* 1 /*
2 * drivers/s390/char/sclp_tty.c 2 * drivers/s390/char/sclp_tty.c
3 * SCLP line mode terminal driver. 3 * SCLP line mode terminal driver.
4 * 4 *
5 * S390 version 5 * S390 version
6 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation 6 * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7 * Author(s): Martin Peschke <mpeschke@de.ibm.com> 7 * Author(s): Martin Peschke <mpeschke@de.ibm.com>
8 * Martin Schwidefsky <schwidefsky@de.ibm.com> 8 * Martin Schwidefsky <schwidefsky@de.ibm.com>
9 */ 9 */
10 10
11 #include <linux/module.h> 11 #include <linux/module.h>
12 #include <linux/kmod.h> 12 #include <linux/kmod.h>
13 #include <linux/tty.h> 13 #include <linux/tty.h>
14 #include <linux/tty_driver.h> 14 #include <linux/tty_driver.h>
15 #include <linux/tty_flip.h> 15 #include <linux/tty_flip.h>
16 #include <linux/err.h> 16 #include <linux/err.h>
17 #include <linux/init.h> 17 #include <linux/init.h>
18 #include <linux/interrupt.h> 18 #include <linux/interrupt.h>
19 #include <linux/gfp.h> 19 #include <linux/gfp.h>
20 #include <asm/uaccess.h> 20 #include <asm/uaccess.h>
21 21
22 #include "ctrlchar.h" 22 #include "ctrlchar.h"
23 #include "sclp.h" 23 #include "sclp.h"
24 #include "sclp_rw.h" 24 #include "sclp_rw.h"
25 #include "sclp_tty.h" 25 #include "sclp_tty.h"
26 26
27 /* 27 /*
28 * size of a buffer that collects single characters coming in 28 * size of a buffer that collects single characters coming in
29 * via sclp_tty_put_char() 29 * via sclp_tty_put_char()
30 */ 30 */
31 #define SCLP_TTY_BUF_SIZE 512 31 #define SCLP_TTY_BUF_SIZE 512
32 32
33 /* 33 /*
34 * There is exactly one SCLP terminal, so we can keep things simple 34 * There is exactly one SCLP terminal, so we can keep things simple
35 * and allocate all variables statically. 35 * and allocate all variables statically.
36 */ 36 */
37 37
38 /* Lock to guard over changes to global variables. */ 38 /* Lock to guard over changes to global variables. */
39 static spinlock_t sclp_tty_lock; 39 static spinlock_t sclp_tty_lock;
40 /* List of free pages that can be used for console output buffering. */ 40 /* List of free pages that can be used for console output buffering. */
41 static struct list_head sclp_tty_pages; 41 static struct list_head sclp_tty_pages;
42 /* List of full struct sclp_buffer structures ready for output. */ 42 /* List of full struct sclp_buffer structures ready for output. */
43 static struct list_head sclp_tty_outqueue; 43 static struct list_head sclp_tty_outqueue;
44 /* Counter how many buffers are emitted. */ 44 /* Counter how many buffers are emitted. */
45 static int sclp_tty_buffer_count; 45 static int sclp_tty_buffer_count;
46 /* Pointer to current console buffer. */ 46 /* Pointer to current console buffer. */
47 static struct sclp_buffer *sclp_ttybuf; 47 static struct sclp_buffer *sclp_ttybuf;
48 /* Timer for delayed output of console messages. */ 48 /* Timer for delayed output of console messages. */
49 static struct timer_list sclp_tty_timer; 49 static struct timer_list sclp_tty_timer;
50 50
51 static struct tty_struct *sclp_tty; 51 static struct tty_struct *sclp_tty;
52 static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE]; 52 static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE];
53 static unsigned short int sclp_tty_chars_count; 53 static unsigned short int sclp_tty_chars_count;
54 54
55 struct tty_driver *sclp_tty_driver; 55 struct tty_driver *sclp_tty_driver;
56 56
57 static int sclp_tty_tolower; 57 static int sclp_tty_tolower;
58 static int sclp_tty_columns = 80; 58 static int sclp_tty_columns = 80;
59 59
60 #define SPACES_PER_TAB 8 60 #define SPACES_PER_TAB 8
61 #define CASE_DELIMITER 0x6c /* to separate upper and lower case (% in EBCDIC) */ 61 #define CASE_DELIMITER 0x6c /* to separate upper and lower case (% in EBCDIC) */
62 62
63 /* This routine is called whenever we try to open a SCLP terminal. */ 63 /* This routine is called whenever we try to open a SCLP terminal. */
64 static int 64 static int
65 sclp_tty_open(struct tty_struct *tty, struct file *filp) 65 sclp_tty_open(struct tty_struct *tty, struct file *filp)
66 { 66 {
67 sclp_tty = tty; 67 sclp_tty = tty;
68 tty->driver_data = NULL; 68 tty->driver_data = NULL;
69 tty->low_latency = 0; 69 tty->low_latency = 0;
70 return 0; 70 return 0;
71 } 71 }
72 72
73 /* This routine is called when the SCLP terminal is closed. */ 73 /* This routine is called when the SCLP terminal is closed. */
74 static void 74 static void
75 sclp_tty_close(struct tty_struct *tty, struct file *filp) 75 sclp_tty_close(struct tty_struct *tty, struct file *filp)
76 { 76 {
77 if (tty->count > 1) 77 if (tty->count > 1)
78 return; 78 return;
79 sclp_tty = NULL; 79 sclp_tty = NULL;
80 } 80 }
81 81
82 /* 82 /*
83 * This routine returns the numbers of characters the tty driver 83 * This routine returns the numbers of characters the tty driver
84 * will accept for queuing to be written. This number is subject 84 * will accept for queuing to be written. This number is subject
85 * to change as output buffers get emptied, or if the output flow 85 * to change as output buffers get emptied, or if the output flow
86 * control is acted. This is not an exact number because not every 86 * control is acted. This is not an exact number because not every
87 * character needs the same space in the sccb. The worst case is 87 * character needs the same space in the sccb. The worst case is
88 * a string of newlines. Every newlines creates a new mto which 88 * a string of newlines. Every newlines creates a new mto which
89 * needs 8 bytes. 89 * needs 8 bytes.
90 */ 90 */
91 static int 91 static int
92 sclp_tty_write_room (struct tty_struct *tty) 92 sclp_tty_write_room (struct tty_struct *tty)
93 { 93 {
94 unsigned long flags; 94 unsigned long flags;
95 struct list_head *l; 95 struct list_head *l;
96 int count; 96 int count;
97 97
98 spin_lock_irqsave(&sclp_tty_lock, flags); 98 spin_lock_irqsave(&sclp_tty_lock, flags);
99 count = 0; 99 count = 0;
100 if (sclp_ttybuf != NULL) 100 if (sclp_ttybuf != NULL)
101 count = sclp_buffer_space(sclp_ttybuf) / sizeof(struct mto); 101 count = sclp_buffer_space(sclp_ttybuf) / sizeof(struct mto);
102 list_for_each(l, &sclp_tty_pages) 102 list_for_each(l, &sclp_tty_pages)
103 count += NR_EMPTY_MTO_PER_SCCB; 103 count += NR_EMPTY_MTO_PER_SCCB;
104 spin_unlock_irqrestore(&sclp_tty_lock, flags); 104 spin_unlock_irqrestore(&sclp_tty_lock, flags);
105 return count; 105 return count;
106 } 106 }
107 107
108 static void 108 static void
109 sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc) 109 sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc)
110 { 110 {
111 unsigned long flags; 111 unsigned long flags;
112 void *page; 112 void *page;
113 113
114 do { 114 do {
115 page = sclp_unmake_buffer(buffer); 115 page = sclp_unmake_buffer(buffer);
116 spin_lock_irqsave(&sclp_tty_lock, flags); 116 spin_lock_irqsave(&sclp_tty_lock, flags);
117 /* Remove buffer from outqueue */ 117 /* Remove buffer from outqueue */
118 list_del(&buffer->list); 118 list_del(&buffer->list);
119 sclp_tty_buffer_count--; 119 sclp_tty_buffer_count--;
120 list_add_tail((struct list_head *) page, &sclp_tty_pages); 120 list_add_tail((struct list_head *) page, &sclp_tty_pages);
121 /* Check if there is a pending buffer on the out queue. */ 121 /* Check if there is a pending buffer on the out queue. */
122 buffer = NULL; 122 buffer = NULL;
123 if (!list_empty(&sclp_tty_outqueue)) 123 if (!list_empty(&sclp_tty_outqueue))
124 buffer = list_entry(sclp_tty_outqueue.next, 124 buffer = list_entry(sclp_tty_outqueue.next,
125 struct sclp_buffer, list); 125 struct sclp_buffer, list);
126 spin_unlock_irqrestore(&sclp_tty_lock, flags); 126 spin_unlock_irqrestore(&sclp_tty_lock, flags);
127 } while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback)); 127 } while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback));
128 /* check if the tty needs a wake up call */ 128 /* check if the tty needs a wake up call */
129 if (sclp_tty != NULL) { 129 if (sclp_tty != NULL) {
130 tty_wakeup(sclp_tty); 130 tty_wakeup(sclp_tty);
131 } 131 }
132 } 132 }
133 133
134 static inline void 134 static inline void
135 __sclp_ttybuf_emit(struct sclp_buffer *buffer) 135 __sclp_ttybuf_emit(struct sclp_buffer *buffer)
136 { 136 {
137 unsigned long flags; 137 unsigned long flags;
138 int count; 138 int count;
139 int rc; 139 int rc;
140 140
141 spin_lock_irqsave(&sclp_tty_lock, flags); 141 spin_lock_irqsave(&sclp_tty_lock, flags);
142 list_add_tail(&buffer->list, &sclp_tty_outqueue); 142 list_add_tail(&buffer->list, &sclp_tty_outqueue);
143 count = sclp_tty_buffer_count++; 143 count = sclp_tty_buffer_count++;
144 spin_unlock_irqrestore(&sclp_tty_lock, flags); 144 spin_unlock_irqrestore(&sclp_tty_lock, flags);
145 if (count) 145 if (count)
146 return; 146 return;
147 rc = sclp_emit_buffer(buffer, sclp_ttybuf_callback); 147 rc = sclp_emit_buffer(buffer, sclp_ttybuf_callback);
148 if (rc) 148 if (rc)
149 sclp_ttybuf_callback(buffer, rc); 149 sclp_ttybuf_callback(buffer, rc);
150 } 150 }
151 151
152 /* 152 /*
153 * When this routine is called from the timer then we flush the 153 * When this routine is called from the timer then we flush the
154 * temporary write buffer. 154 * temporary write buffer.
155 */ 155 */
156 static void 156 static void
157 sclp_tty_timeout(unsigned long data) 157 sclp_tty_timeout(unsigned long data)
158 { 158 {
159 unsigned long flags; 159 unsigned long flags;
160 struct sclp_buffer *buf; 160 struct sclp_buffer *buf;
161 161
162 spin_lock_irqsave(&sclp_tty_lock, flags); 162 spin_lock_irqsave(&sclp_tty_lock, flags);
163 buf = sclp_ttybuf; 163 buf = sclp_ttybuf;
164 sclp_ttybuf = NULL; 164 sclp_ttybuf = NULL;
165 spin_unlock_irqrestore(&sclp_tty_lock, flags); 165 spin_unlock_irqrestore(&sclp_tty_lock, flags);
166 166
167 if (buf != NULL) { 167 if (buf != NULL) {
168 __sclp_ttybuf_emit(buf); 168 __sclp_ttybuf_emit(buf);
169 } 169 }
170 } 170 }
171 171
172 /* 172 /*
173 * Write a string to the sclp tty. 173 * Write a string to the sclp tty.
174 */ 174 */
175 static int sclp_tty_write_string(const unsigned char *str, int count, int may_fail) 175 static int sclp_tty_write_string(const unsigned char *str, int count, int may_fail)
176 { 176 {
177 unsigned long flags; 177 unsigned long flags;
178 void *page; 178 void *page;
179 int written; 179 int written;
180 int overall_written; 180 int overall_written;
181 struct sclp_buffer *buf; 181 struct sclp_buffer *buf;
182 182
183 if (count <= 0) 183 if (count <= 0)
184 return 0; 184 return 0;
185 overall_written = 0; 185 overall_written = 0;
186 spin_lock_irqsave(&sclp_tty_lock, flags); 186 spin_lock_irqsave(&sclp_tty_lock, flags);
187 do { 187 do {
188 /* Create a sclp output buffer if none exists yet */ 188 /* Create a sclp output buffer if none exists yet */
189 if (sclp_ttybuf == NULL) { 189 if (sclp_ttybuf == NULL) {
190 while (list_empty(&sclp_tty_pages)) { 190 while (list_empty(&sclp_tty_pages)) {
191 spin_unlock_irqrestore(&sclp_tty_lock, flags); 191 spin_unlock_irqrestore(&sclp_tty_lock, flags);
192 if (may_fail) 192 if (may_fail)
193 goto out; 193 goto out;
194 else 194 else
195 sclp_sync_wait(); 195 sclp_sync_wait();
196 spin_lock_irqsave(&sclp_tty_lock, flags); 196 spin_lock_irqsave(&sclp_tty_lock, flags);
197 } 197 }
198 page = sclp_tty_pages.next; 198 page = sclp_tty_pages.next;
199 list_del((struct list_head *) page); 199 list_del((struct list_head *) page);
200 sclp_ttybuf = sclp_make_buffer(page, sclp_tty_columns, 200 sclp_ttybuf = sclp_make_buffer(page, sclp_tty_columns,
201 SPACES_PER_TAB); 201 SPACES_PER_TAB);
202 } 202 }
203 /* try to write the string to the current output buffer */ 203 /* try to write the string to the current output buffer */
204 written = sclp_write(sclp_ttybuf, str, count); 204 written = sclp_write(sclp_ttybuf, str, count);
205 overall_written += written; 205 overall_written += written;
206 if (written == count) 206 if (written == count)
207 break; 207 break;
208 /* 208 /*
209 * Not all characters could be written to the current 209 * Not all characters could be written to the current
210 * output buffer. Emit the buffer, create a new buffer 210 * output buffer. Emit the buffer, create a new buffer
211 * and then output the rest of the string. 211 * and then output the rest of the string.
212 */ 212 */
213 buf = sclp_ttybuf; 213 buf = sclp_ttybuf;
214 sclp_ttybuf = NULL; 214 sclp_ttybuf = NULL;
215 spin_unlock_irqrestore(&sclp_tty_lock, flags); 215 spin_unlock_irqrestore(&sclp_tty_lock, flags);
216 __sclp_ttybuf_emit(buf); 216 __sclp_ttybuf_emit(buf);
217 spin_lock_irqsave(&sclp_tty_lock, flags); 217 spin_lock_irqsave(&sclp_tty_lock, flags);
218 str += written; 218 str += written;
219 count -= written; 219 count -= written;
220 } while (count > 0); 220 } while (count > 0);
221 /* Setup timer to output current console buffer after 1/10 second */ 221 /* Setup timer to output current console buffer after 1/10 second */
222 if (sclp_ttybuf && sclp_chars_in_buffer(sclp_ttybuf) && 222 if (sclp_ttybuf && sclp_chars_in_buffer(sclp_ttybuf) &&
223 !timer_pending(&sclp_tty_timer)) { 223 !timer_pending(&sclp_tty_timer)) {
224 init_timer(&sclp_tty_timer); 224 init_timer(&sclp_tty_timer);
225 sclp_tty_timer.function = sclp_tty_timeout; 225 sclp_tty_timer.function = sclp_tty_timeout;
226 sclp_tty_timer.data = 0UL; 226 sclp_tty_timer.data = 0UL;
227 sclp_tty_timer.expires = jiffies + HZ/10; 227 sclp_tty_timer.expires = jiffies + HZ/10;
228 add_timer(&sclp_tty_timer); 228 add_timer(&sclp_tty_timer);
229 } 229 }
230 spin_unlock_irqrestore(&sclp_tty_lock, flags); 230 spin_unlock_irqrestore(&sclp_tty_lock, flags);
231 out: 231 out:
232 return overall_written; 232 return overall_written;
233 } 233 }
234 234
235 /* 235 /*
236 * This routine is called by the kernel to write a series of characters to the 236 * This routine is called by the kernel to write a series of characters to the
237 * tty device. The characters may come from user space or kernel space. This 237 * tty device. The characters may come from user space or kernel space. This
238 * routine will return the number of characters actually accepted for writing. 238 * routine will return the number of characters actually accepted for writing.
239 */ 239 */
240 static int 240 static int
241 sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) 241 sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
242 { 242 {
243 if (sclp_tty_chars_count > 0) { 243 if (sclp_tty_chars_count > 0) {
244 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); 244 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
245 sclp_tty_chars_count = 0; 245 sclp_tty_chars_count = 0;
246 } 246 }
247 return sclp_tty_write_string(buf, count, 1); 247 return sclp_tty_write_string(buf, count, 1);
248 } 248 }
249 249
250 /* 250 /*
251 * This routine is called by the kernel to write a single character to the tty 251 * This routine is called by the kernel to write a single character to the tty
252 * device. If the kernel uses this routine, it must call the flush_chars() 252 * device. If the kernel uses this routine, it must call the flush_chars()
253 * routine (if defined) when it is done stuffing characters into the driver. 253 * routine (if defined) when it is done stuffing characters into the driver.
254 * 254 *
255 * Characters provided to sclp_tty_put_char() are buffered by the SCLP driver. 255 * Characters provided to sclp_tty_put_char() are buffered by the SCLP driver.
256 * If the given character is a '\n' the contents of the SCLP write buffer 256 * If the given character is a '\n' the contents of the SCLP write buffer
257 * - including previous characters from sclp_tty_put_char() and strings from 257 * - including previous characters from sclp_tty_put_char() and strings from
258 * sclp_write() without final '\n' - will be written. 258 * sclp_write() without final '\n' - will be written.
259 */ 259 */
260 static int 260 static int
261 sclp_tty_put_char(struct tty_struct *tty, unsigned char ch) 261 sclp_tty_put_char(struct tty_struct *tty, unsigned char ch)
262 { 262 {
263 sclp_tty_chars[sclp_tty_chars_count++] = ch; 263 sclp_tty_chars[sclp_tty_chars_count++] = ch;
264 if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) { 264 if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) {
265 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); 265 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
266 sclp_tty_chars_count = 0; 266 sclp_tty_chars_count = 0;
267 } 267 }
268 return 1; 268 return 1;
269 } 269 }
270 270
271 /* 271 /*
272 * This routine is called by the kernel after it has written a series of 272 * This routine is called by the kernel after it has written a series of
273 * characters to the tty device using put_char(). 273 * characters to the tty device using put_char().
274 */ 274 */
275 static void 275 static void
276 sclp_tty_flush_chars(struct tty_struct *tty) 276 sclp_tty_flush_chars(struct tty_struct *tty)
277 { 277 {
278 if (sclp_tty_chars_count > 0) { 278 if (sclp_tty_chars_count > 0) {
279 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); 279 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
280 sclp_tty_chars_count = 0; 280 sclp_tty_chars_count = 0;
281 } 281 }
282 } 282 }
283 283
284 /* 284 /*
285 * This routine returns the number of characters in the write buffer of the 285 * This routine returns the number of characters in the write buffer of the
286 * SCLP driver. The provided number includes all characters that are stored 286 * SCLP driver. The provided number includes all characters that are stored
287 * in the SCCB (will be written next time the SCLP is not busy) as well as 287 * in the SCCB (will be written next time the SCLP is not busy) as well as
288 * characters in the write buffer (will not be written as long as there is a 288 * characters in the write buffer (will not be written as long as there is a
289 * final line feed missing). 289 * final line feed missing).
290 */ 290 */
291 static int 291 static int
292 sclp_tty_chars_in_buffer(struct tty_struct *tty) 292 sclp_tty_chars_in_buffer(struct tty_struct *tty)
293 { 293 {
294 unsigned long flags; 294 unsigned long flags;
295 struct list_head *l; 295 struct list_head *l;
296 struct sclp_buffer *t; 296 struct sclp_buffer *t;
297 int count; 297 int count;
298 298
299 spin_lock_irqsave(&sclp_tty_lock, flags); 299 spin_lock_irqsave(&sclp_tty_lock, flags);
300 count = 0; 300 count = 0;
301 if (sclp_ttybuf != NULL) 301 if (sclp_ttybuf != NULL)
302 count = sclp_chars_in_buffer(sclp_ttybuf); 302 count = sclp_chars_in_buffer(sclp_ttybuf);
303 list_for_each(l, &sclp_tty_outqueue) { 303 list_for_each(l, &sclp_tty_outqueue) {
304 t = list_entry(l, struct sclp_buffer, list); 304 t = list_entry(l, struct sclp_buffer, list);
305 count += sclp_chars_in_buffer(t); 305 count += sclp_chars_in_buffer(t);
306 } 306 }
307 spin_unlock_irqrestore(&sclp_tty_lock, flags); 307 spin_unlock_irqrestore(&sclp_tty_lock, flags);
308 return count; 308 return count;
309 } 309 }
310 310
311 /* 311 /*
312 * removes all content from buffers of low level driver 312 * removes all content from buffers of low level driver
313 */ 313 */
314 static void 314 static void
315 sclp_tty_flush_buffer(struct tty_struct *tty) 315 sclp_tty_flush_buffer(struct tty_struct *tty)
316 { 316 {
317 if (sclp_tty_chars_count > 0) { 317 if (sclp_tty_chars_count > 0) {
318 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); 318 sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0);
319 sclp_tty_chars_count = 0; 319 sclp_tty_chars_count = 0;
320 } 320 }
321 } 321 }
322 322
323 /* 323 /*
324 * push input to tty 324 * push input to tty
325 */ 325 */
326 static void 326 static void
327 sclp_tty_input(unsigned char* buf, unsigned int count) 327 sclp_tty_input(unsigned char* buf, unsigned int count)
328 { 328 {
329 unsigned int cchar; 329 unsigned int cchar;
330 330
331 /* 331 /*
332 * If this tty driver is currently closed 332 * If this tty driver is currently closed
333 * then throw the received input away. 333 * then throw the received input away.
334 */ 334 */
335 if (sclp_tty == NULL) 335 if (sclp_tty == NULL)
336 return; 336 return;
337 cchar = ctrlchar_handle(buf, count, sclp_tty); 337 cchar = ctrlchar_handle(buf, count, sclp_tty);
338 switch (cchar & CTRLCHAR_MASK) { 338 switch (cchar & CTRLCHAR_MASK) {
339 case CTRLCHAR_SYSRQ: 339 case CTRLCHAR_SYSRQ:
340 break; 340 break;
341 case CTRLCHAR_CTRL: 341 case CTRLCHAR_CTRL:
342 tty_insert_flip_char(sclp_tty, cchar, TTY_NORMAL); 342 tty_insert_flip_char(sclp_tty, cchar, TTY_NORMAL);
343 tty_flip_buffer_push(sclp_tty); 343 tty_flip_buffer_push(sclp_tty);
344 break; 344 break;
345 case CTRLCHAR_NONE: 345 case CTRLCHAR_NONE:
346 /* send (normal) input to line discipline */ 346 /* send (normal) input to line discipline */
347 if (count < 2 || 347 if (count < 2 ||
348 (strncmp((const char *) buf + count - 2, "^n", 2) && 348 (strncmp((const char *) buf + count - 2, "^n", 2) &&
349 strncmp((const char *) buf + count - 2, "\252n", 2))) { 349 strncmp((const char *) buf + count - 2, "\252n", 2))) {
350 /* add the auto \n */ 350 /* add the auto \n */
351 tty_insert_flip_string(sclp_tty, buf, count); 351 tty_insert_flip_string(sclp_tty, buf, count);
352 tty_insert_flip_char(sclp_tty, '\n', TTY_NORMAL); 352 tty_insert_flip_char(sclp_tty, '\n', TTY_NORMAL);
353 } else 353 } else
354 tty_insert_flip_string(sclp_tty, buf, count - 2); 354 tty_insert_flip_string(sclp_tty, buf, count - 2);
355 tty_flip_buffer_push(sclp_tty); 355 tty_flip_buffer_push(sclp_tty);
356 break; 356 break;
357 } 357 }
358 } 358 }
359 359
360 /* 360 /*
361 * get a EBCDIC string in upper/lower case, 361 * get a EBCDIC string in upper/lower case,
362 * find out characters in lower/upper case separated by a special character, 362 * find out characters in lower/upper case separated by a special character,
363 * modifiy original string, 363 * modifiy original string,
364 * returns length of resulting string 364 * returns length of resulting string
365 */ 365 */
366 static int sclp_switch_cases(unsigned char *buf, int count) 366 static int sclp_switch_cases(unsigned char *buf, int count)
367 { 367 {
368 unsigned char *ip, *op; 368 unsigned char *ip, *op;
369 int toggle; 369 int toggle;
370 370
371 /* initially changing case is off */ 371 /* initially changing case is off */
372 toggle = 0; 372 toggle = 0;
373 ip = op = buf; 373 ip = op = buf;
374 while (count-- > 0) { 374 while (count-- > 0) {
375 /* compare with special character */ 375 /* compare with special character */
376 if (*ip == CASE_DELIMITER) { 376 if (*ip == CASE_DELIMITER) {
377 /* followed by another special character? */ 377 /* followed by another special character? */
378 if (count && ip[1] == CASE_DELIMITER) { 378 if (count && ip[1] == CASE_DELIMITER) {
379 /* 379 /*
380 * ... then put a single copy of the special 380 * ... then put a single copy of the special
381 * character to the output string 381 * character to the output string
382 */ 382 */
383 *op++ = *ip++; 383 *op++ = *ip++;
384 count--; 384 count--;
385 } else 385 } else
386 /* 386 /*
387 * ... special character follower by a normal 387 * ... special character follower by a normal
388 * character toggles the case change behaviour 388 * character toggles the case change behaviour
389 */ 389 */
390 toggle = ~toggle; 390 toggle = ~toggle;
391 /* skip special character */ 391 /* skip special character */
392 ip++; 392 ip++;
393 } else 393 } else
394 /* not the special character */ 394 /* not the special character */
395 if (toggle) 395 if (toggle)
396 /* but case switching is on */ 396 /* but case switching is on */
397 if (sclp_tty_tolower) 397 if (sclp_tty_tolower)
398 /* switch to uppercase */ 398 /* switch to uppercase */
399 *op++ = _ebc_toupper[(int) *ip++]; 399 *op++ = _ebc_toupper[(int) *ip++];
400 else 400 else
401 /* switch to lowercase */ 401 /* switch to lowercase */
402 *op++ = _ebc_tolower[(int) *ip++]; 402 *op++ = _ebc_tolower[(int) *ip++];
403 else 403 else
404 /* no case switching, copy the character */ 404 /* no case switching, copy the character */
405 *op++ = *ip++; 405 *op++ = *ip++;
406 } 406 }
407 /* return length of reformatted string. */ 407 /* return length of reformatted string. */
408 return op - buf; 408 return op - buf;
409 } 409 }
410 410
411 static void 411 static void sclp_get_input(struct gds_subvector *sv)
412 sclp_get_input(unsigned char *start, unsigned char *end)
413 { 412 {
413 unsigned char *str;
414 int count; 414 int count;
415 415
416 count = end - start; 416 str = (unsigned char *) (sv + 1);
417 count = sv->length - sizeof(*sv);
417 if (sclp_tty_tolower) 418 if (sclp_tty_tolower)
418 EBC_TOLOWER(start, count); 419 EBC_TOLOWER(str, count);
419 count = sclp_switch_cases(start, count); 420 count = sclp_switch_cases(str, count);
420 /* convert EBCDIC to ASCII (modify original input in SCCB) */ 421 /* convert EBCDIC to ASCII (modify original input in SCCB) */
421 sclp_ebcasc_str(start, count); 422 sclp_ebcasc_str(str, count);
422 423
423 /* transfer input to high level driver */ 424 /* transfer input to high level driver */
424 sclp_tty_input(start, count); 425 sclp_tty_input(str, count);
425 } 426 }
426 427
427 static inline struct gds_vector * 428 static inline void sclp_eval_selfdeftextmsg(struct gds_subvector *sv)
428 find_gds_vector(struct gds_vector *start, struct gds_vector *end, u16 id)
429 { 429 {
430 struct gds_vector *vec; 430 void *end;
431 431
432 for (vec = start; vec < end; vec = (void *) vec + vec->length) 432 end = (void *) sv + sv->length;
433 if (vec->gds_id == id) 433 for (sv = sv + 1; (void *) sv < end; sv = (void *) sv + sv->length)
434 return vec; 434 if (sv->key == 0x30)
435 return NULL; 435 sclp_get_input(sv);
436 } 436 }
437 437
438 static inline struct gds_subvector * 438 static inline void sclp_eval_textcmd(struct gds_vector *v)
439 find_gds_subvector(struct gds_subvector *start,
440 struct gds_subvector *end, u8 key)
441 { 439 {
442 struct gds_subvector *subvec; 440 struct gds_subvector *sv;
441 void *end;
443 442
444 for (subvec = start; subvec < end; 443 end = (void *) v + v->length;
445 subvec = (void *) subvec + subvec->length) 444 for (sv = (struct gds_subvector *) (v + 1);
446 if (subvec->key == key) 445 (void *) sv < end; sv = (void *) sv + sv->length)
447 return subvec; 446 if (sv->key == GDS_KEY_SELFDEFTEXTMSG)
448 return NULL; 447 sclp_eval_selfdeftextmsg(sv);
449 }
450 448
451 static inline void
452 sclp_eval_selfdeftextmsg(struct gds_subvector *start,
453 struct gds_subvector *end)
454 {
455 struct gds_subvector *subvec;
456
457 subvec = start;
458 while (subvec < end) {
459 subvec = find_gds_subvector(subvec, end, 0x30);
460 if (!subvec)
461 break;
462 sclp_get_input((unsigned char *)(subvec + 1),
463 (unsigned char *) subvec + subvec->length);
464 subvec = (void *) subvec + subvec->length;
465 }
466 } 449 }
467 450
468 static inline void 451 static inline void sclp_eval_cpmsu(struct gds_vector *v)
469 sclp_eval_textcmd(struct gds_subvector *start,
470 struct gds_subvector *end)
471 { 452 {
472 struct gds_subvector *subvec; 453 void *end;
473 454
474 subvec = start; 455 end = (void *) v + v->length;
475 while (subvec < end) { 456 for (v = v + 1; (void *) v < end; v = (void *) v + v->length)
476 subvec = find_gds_subvector(subvec, end, 457 if (v->gds_id == GDS_ID_TEXTCMD)
477 GDS_KEY_SELFDEFTEXTMSG); 458 sclp_eval_textcmd(v);
478 if (!subvec)
479 break;
480 sclp_eval_selfdeftextmsg((struct gds_subvector *)(subvec + 1),
481 (void *)subvec + subvec->length);
482 subvec = (void *) subvec + subvec->length;
483 }
484 } 459 }
485 460
486 static inline void
487 sclp_eval_cpmsu(struct gds_vector *start, struct gds_vector *end)
488 {
489 struct gds_vector *vec;
490 461
491 vec = start; 462 static inline void sclp_eval_mdsmu(struct gds_vector *v)
492 while (vec < end) {
493 vec = find_gds_vector(vec, end, GDS_ID_TEXTCMD);
494 if (!vec)
495 break;
496 sclp_eval_textcmd((struct gds_subvector *)(vec + 1),
497 (void *) vec + vec->length);
498 vec = (void *) vec + vec->length;
499 }
500 }
501
502
503 static inline void
504 sclp_eval_mdsmu(struct gds_vector *start, void *end)
505 { 463 {
506 struct gds_vector *vec; 464 v = sclp_find_gds_vector(v + 1, (void *) v + v->length, GDS_ID_CPMSU);
507 465 if (v)
508 vec = find_gds_vector(start, end, GDS_ID_CPMSU); 466 sclp_eval_cpmsu(v);
509 if (vec)
510 sclp_eval_cpmsu(vec + 1, (void *) vec + vec->length);
511 } 467 }
512 468
513 static void 469 static void sclp_tty_receiver(struct evbuf_header *evbuf)
514 sclp_tty_receiver(struct evbuf_header *evbuf)
515 { 470 {
516 struct gds_vector *start, *end, *vec; 471 struct gds_vector *v;
517 472
518 start = (struct gds_vector *)(evbuf + 1); 473 v = sclp_find_gds_vector(evbuf + 1, (void *) evbuf + evbuf->length,
519 end = (void *) evbuf + evbuf->length; 474 GDS_ID_MDSMU);
520 vec = find_gds_vector(start, end, GDS_ID_MDSMU); 475 if (v)
521 if (vec) 476 sclp_eval_mdsmu(v);
522 sclp_eval_mdsmu(vec + 1, (void *) vec + vec->length);
523 } 477 }
524 478
525 static void 479 static void
526 sclp_tty_state_change(struct sclp_register *reg) 480 sclp_tty_state_change(struct sclp_register *reg)
527 { 481 {
528 } 482 }
529 483
530 static struct sclp_register sclp_input_event = 484 static struct sclp_register sclp_input_event =
531 { 485 {
532 .receive_mask = EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK, 486 .receive_mask = EVTYP_OPCMD_MASK | EVTYP_PMSGCMD_MASK,
533 .state_change_fn = sclp_tty_state_change, 487 .state_change_fn = sclp_tty_state_change,
534 .receiver_fn = sclp_tty_receiver 488 .receiver_fn = sclp_tty_receiver
535 }; 489 };
536 490
537 static const struct tty_operations sclp_ops = { 491 static const struct tty_operations sclp_ops = {
538 .open = sclp_tty_open, 492 .open = sclp_tty_open,
539 .close = sclp_tty_close, 493 .close = sclp_tty_close,
540 .write = sclp_tty_write, 494 .write = sclp_tty_write,
541 .put_char = sclp_tty_put_char, 495 .put_char = sclp_tty_put_char,
542 .flush_chars = sclp_tty_flush_chars, 496 .flush_chars = sclp_tty_flush_chars,
543 .write_room = sclp_tty_write_room, 497 .write_room = sclp_tty_write_room,
544 .chars_in_buffer = sclp_tty_chars_in_buffer, 498 .chars_in_buffer = sclp_tty_chars_in_buffer,
545 .flush_buffer = sclp_tty_flush_buffer, 499 .flush_buffer = sclp_tty_flush_buffer,
546 }; 500 };
547 501
548 static int __init 502 static int __init
549 sclp_tty_init(void) 503 sclp_tty_init(void)
550 { 504 {
551 struct tty_driver *driver; 505 struct tty_driver *driver;
552 void *page; 506 void *page;
553 int i; 507 int i;
554 int rc; 508 int rc;
555 509
556 if (!CONSOLE_IS_SCLP) 510 if (!CONSOLE_IS_SCLP)
557 return 0; 511 return 0;
558 driver = alloc_tty_driver(1); 512 driver = alloc_tty_driver(1);
559 if (!driver) 513 if (!driver)
560 return -ENOMEM; 514 return -ENOMEM;
561 515
562 rc = sclp_rw_init(); 516 rc = sclp_rw_init();
563 if (rc) { 517 if (rc) {
564 put_tty_driver(driver); 518 put_tty_driver(driver);
565 return rc; 519 return rc;
566 } 520 }
567 /* Allocate pages for output buffering */ 521 /* Allocate pages for output buffering */
568 INIT_LIST_HEAD(&sclp_tty_pages); 522 INIT_LIST_HEAD(&sclp_tty_pages);
569 for (i = 0; i < MAX_KMEM_PAGES; i++) { 523 for (i = 0; i < MAX_KMEM_PAGES; i++) {
570 page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 524 page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
571 if (page == NULL) { 525 if (page == NULL) {
572 put_tty_driver(driver); 526 put_tty_driver(driver);
573 return -ENOMEM; 527 return -ENOMEM;
574 } 528 }
575 list_add_tail((struct list_head *) page, &sclp_tty_pages); 529 list_add_tail((struct list_head *) page, &sclp_tty_pages);
576 } 530 }
577 INIT_LIST_HEAD(&sclp_tty_outqueue); 531 INIT_LIST_HEAD(&sclp_tty_outqueue);
578 spin_lock_init(&sclp_tty_lock); 532 spin_lock_init(&sclp_tty_lock);
579 init_timer(&sclp_tty_timer); 533 init_timer(&sclp_tty_timer);
580 sclp_ttybuf = NULL; 534 sclp_ttybuf = NULL;
581 sclp_tty_buffer_count = 0; 535 sclp_tty_buffer_count = 0;
582 if (MACHINE_IS_VM) { 536 if (MACHINE_IS_VM) {
583 /* 537 /*
584 * save 4 characters for the CPU number 538 * save 4 characters for the CPU number
585 * written at start of each line by VM/CP 539 * written at start of each line by VM/CP
586 */ 540 */
587 sclp_tty_columns = 76; 541 sclp_tty_columns = 76;
588 /* case input lines to lowercase */ 542 /* case input lines to lowercase */
589 sclp_tty_tolower = 1; 543 sclp_tty_tolower = 1;
590 } 544 }
591 sclp_tty_chars_count = 0; 545 sclp_tty_chars_count = 0;
592 sclp_tty = NULL; 546 sclp_tty = NULL;
593 547
594 rc = sclp_register(&sclp_input_event); 548 rc = sclp_register(&sclp_input_event);
595 if (rc) { 549 if (rc) {
596 put_tty_driver(driver); 550 put_tty_driver(driver);
597 return rc; 551 return rc;
598 } 552 }
599 553
600 driver->owner = THIS_MODULE; 554 driver->owner = THIS_MODULE;
601 driver->driver_name = "sclp_line"; 555 driver->driver_name = "sclp_line";
602 driver->name = "sclp_line"; 556 driver->name = "sclp_line";
603 driver->major = TTY_MAJOR; 557 driver->major = TTY_MAJOR;
604 driver->minor_start = 64; 558 driver->minor_start = 64;
605 driver->type = TTY_DRIVER_TYPE_SYSTEM; 559 driver->type = TTY_DRIVER_TYPE_SYSTEM;
606 driver->subtype = SYSTEM_TYPE_TTY; 560 driver->subtype = SYSTEM_TYPE_TTY;
607 driver->init_termios = tty_std_termios; 561 driver->init_termios = tty_std_termios;
608 driver->init_termios.c_iflag = IGNBRK | IGNPAR; 562 driver->init_termios.c_iflag = IGNBRK | IGNPAR;
609 driver->init_termios.c_oflag = ONLCR | XTABS; 563 driver->init_termios.c_oflag = ONLCR | XTABS;
610 driver->init_termios.c_lflag = ISIG | ECHO; 564 driver->init_termios.c_lflag = ISIG | ECHO;
611 driver->flags = TTY_DRIVER_REAL_RAW; 565 driver->flags = TTY_DRIVER_REAL_RAW;
612 tty_set_operations(driver, &sclp_ops); 566 tty_set_operations(driver, &sclp_ops);
613 rc = tty_register_driver(driver); 567 rc = tty_register_driver(driver);
614 if (rc) { 568 if (rc) {
615 put_tty_driver(driver); 569 put_tty_driver(driver);
616 return rc; 570 return rc;
617 } 571 }
618 sclp_tty_driver = driver; 572 sclp_tty_driver = driver;
619 return 0; 573 return 0;