Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / s390 / cio / ioasm.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Channel subsystem I/O instructions.
4  */
5
6 #include <linux/export.h>
7
8 #include <asm/chpid.h>
9 #include <asm/schid.h>
10 #include <asm/crw.h>
11
12 #include "ioasm.h"
13 #include "orb.h"
14 #include "cio.h"
15
16 static inline int __stsch(struct subchannel_id schid, struct schib *addr)
17 {
18         register struct subchannel_id reg1 asm ("1") = schid;
19         int ccode = -EIO;
20
21         asm volatile(
22                 "       stsch   0(%3)\n"
23                 "0:     ipm     %0\n"
24                 "       srl     %0,28\n"
25                 "1:\n"
26                 EX_TABLE(0b, 1b)
27                 : "+d" (ccode), "=m" (*addr)
28                 : "d" (reg1), "a" (addr)
29                 : "cc");
30         return ccode;
31 }
32
33 int stsch(struct subchannel_id schid, struct schib *addr)
34 {
35         int ccode;
36
37         ccode = __stsch(schid, addr);
38         trace_s390_cio_stsch(schid, addr, ccode);
39
40         return ccode;
41 }
42 EXPORT_SYMBOL(stsch);
43
44 static inline int __msch(struct subchannel_id schid, struct schib *addr)
45 {
46         register struct subchannel_id reg1 asm ("1") = schid;
47         int ccode = -EIO;
48
49         asm volatile(
50                 "       msch    0(%2)\n"
51                 "0:     ipm     %0\n"
52                 "       srl     %0,28\n"
53                 "1:\n"
54                 EX_TABLE(0b, 1b)
55                 : "+d" (ccode)
56                 : "d" (reg1), "a" (addr), "m" (*addr)
57                 : "cc");
58         return ccode;
59 }
60
61 int msch(struct subchannel_id schid, struct schib *addr)
62 {
63         int ccode;
64
65         ccode = __msch(schid, addr);
66         trace_s390_cio_msch(schid, addr, ccode);
67
68         return ccode;
69 }
70
71 static inline int __tsch(struct subchannel_id schid, struct irb *addr)
72 {
73         register struct subchannel_id reg1 asm ("1") = schid;
74         int ccode;
75
76         asm volatile(
77                 "       tsch    0(%3)\n"
78                 "       ipm     %0\n"
79                 "       srl     %0,28"
80                 : "=d" (ccode), "=m" (*addr)
81                 : "d" (reg1), "a" (addr)
82                 : "cc");
83         return ccode;
84 }
85
86 int tsch(struct subchannel_id schid, struct irb *addr)
87 {
88         int ccode;
89
90         ccode = __tsch(schid, addr);
91         trace_s390_cio_tsch(schid, addr, ccode);
92
93         return ccode;
94 }
95
96 static inline int __ssch(struct subchannel_id schid, union orb *addr)
97 {
98         register struct subchannel_id reg1 asm("1") = schid;
99         int ccode = -EIO;
100
101         asm volatile(
102                 "       ssch    0(%2)\n"
103                 "0:     ipm     %0\n"
104                 "       srl     %0,28\n"
105                 "1:\n"
106                 EX_TABLE(0b, 1b)
107                 : "+d" (ccode)
108                 : "d" (reg1), "a" (addr), "m" (*addr)
109                 : "cc", "memory");
110         return ccode;
111 }
112
113 int ssch(struct subchannel_id schid, union orb *addr)
114 {
115         int ccode;
116
117         ccode = __ssch(schid, addr);
118         trace_s390_cio_ssch(schid, addr, ccode);
119
120         return ccode;
121 }
122 EXPORT_SYMBOL(ssch);
123
124 static inline int __csch(struct subchannel_id schid)
125 {
126         register struct subchannel_id reg1 asm("1") = schid;
127         int ccode;
128
129         asm volatile(
130                 "       csch\n"
131                 "       ipm     %0\n"
132                 "       srl     %0,28"
133                 : "=d" (ccode)
134                 : "d" (reg1)
135                 : "cc");
136         return ccode;
137 }
138
139 int csch(struct subchannel_id schid)
140 {
141         int ccode;
142
143         ccode = __csch(schid);
144         trace_s390_cio_csch(schid, ccode);
145
146         return ccode;
147 }
148 EXPORT_SYMBOL(csch);
149
150 int tpi(struct tpi_info *addr)
151 {
152         int ccode;
153
154         asm volatile(
155                 "       tpi     0(%2)\n"
156                 "       ipm     %0\n"
157                 "       srl     %0,28"
158                 : "=d" (ccode), "=m" (*addr)
159                 : "a" (addr)
160                 : "cc");
161         trace_s390_cio_tpi(addr, ccode);
162
163         return ccode;
164 }
165
166 int chsc(void *chsc_area)
167 {
168         typedef struct { char _[4096]; } addr_type;
169         int cc = -EIO;
170
171         asm volatile(
172                 "       .insn   rre,0xb25f0000,%2,0\n"
173                 "0:     ipm     %0\n"
174                 "       srl     %0,28\n"
175                 "1:\n"
176                 EX_TABLE(0b, 1b)
177                 : "+d" (cc), "=m" (*(addr_type *) chsc_area)
178                 : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
179                 : "cc");
180         trace_s390_cio_chsc(chsc_area, cc);
181
182         return cc;
183 }
184 EXPORT_SYMBOL(chsc);
185
186 static inline int __rsch(struct subchannel_id schid)
187 {
188         register struct subchannel_id reg1 asm("1") = schid;
189         int ccode;
190
191         asm volatile(
192                 "       rsch\n"
193                 "       ipm     %0\n"
194                 "       srl     %0,28"
195                 : "=d" (ccode)
196                 : "d" (reg1)
197                 : "cc", "memory");
198
199         return ccode;
200 }
201
202 int rsch(struct subchannel_id schid)
203 {
204         int ccode;
205
206         ccode = __rsch(schid);
207         trace_s390_cio_rsch(schid, ccode);
208
209         return ccode;
210 }
211
212 static inline int __hsch(struct subchannel_id schid)
213 {
214         register struct subchannel_id reg1 asm("1") = schid;
215         int ccode;
216
217         asm volatile(
218                 "       hsch\n"
219                 "       ipm     %0\n"
220                 "       srl     %0,28"
221                 : "=d" (ccode)
222                 : "d" (reg1)
223                 : "cc");
224         return ccode;
225 }
226
227 int hsch(struct subchannel_id schid)
228 {
229         int ccode;
230
231         ccode = __hsch(schid);
232         trace_s390_cio_hsch(schid, ccode);
233
234         return ccode;
235 }
236 EXPORT_SYMBOL(hsch);
237
238 static inline int __xsch(struct subchannel_id schid)
239 {
240         register struct subchannel_id reg1 asm("1") = schid;
241         int ccode;
242
243         asm volatile(
244                 "       xsch\n"
245                 "       ipm     %0\n"
246                 "       srl     %0,28"
247                 : "=d" (ccode)
248                 : "d" (reg1)
249                 : "cc");
250         return ccode;
251 }
252
253 int xsch(struct subchannel_id schid)
254 {
255         int ccode;
256
257         ccode = __xsch(schid);
258         trace_s390_cio_xsch(schid, ccode);
259
260         return ccode;
261 }
262
263 int stcrw(struct crw *crw)
264 {
265         int ccode;
266
267         asm volatile(
268                 "       stcrw   0(%2)\n"
269                 "       ipm     %0\n"
270                 "       srl     %0,28\n"
271                 : "=d" (ccode), "=m" (*crw)
272                 : "a" (crw)
273                 : "cc");
274         trace_s390_cio_stcrw(crw, ccode);
275
276         return ccode;
277 }