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