xref: /openbmc/linux/drivers/s390/cio/ioasm.c (revision b94b10aa)
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;
169 
170 	asm volatile(
171 		"	.insn	rre,0xb25f0000,%2,0\n"
172 		"	ipm	%0\n"
173 		"	srl	%0,28\n"
174 		: "=d" (cc), "=m" (*(addr_type *) chsc_area)
175 		: "d" (chsc_area), "m" (*(addr_type *) chsc_area)
176 		: "cc");
177 	trace_s390_cio_chsc(chsc_area, cc);
178 
179 	return cc;
180 }
181 EXPORT_SYMBOL(chsc);
182 
183 static inline int __rchp(struct chp_id chpid)
184 {
185 	register struct chp_id reg1 asm ("1") = chpid;
186 	int ccode;
187 
188 	asm volatile(
189 		"	lr	1,%1\n"
190 		"	rchp\n"
191 		"	ipm	%0\n"
192 		"	srl	%0,28"
193 		: "=d" (ccode) : "d" (reg1) : "cc");
194 	return ccode;
195 }
196 
197 int rchp(struct chp_id chpid)
198 {
199 	int ccode;
200 
201 	ccode = __rchp(chpid);
202 	trace_s390_cio_rchp(chpid, ccode);
203 
204 	return ccode;
205 }
206 
207 static inline int __rsch(struct subchannel_id schid)
208 {
209 	register struct subchannel_id reg1 asm("1") = schid;
210 	int ccode;
211 
212 	asm volatile(
213 		"	rsch\n"
214 		"	ipm	%0\n"
215 		"	srl	%0,28"
216 		: "=d" (ccode)
217 		: "d" (reg1)
218 		: "cc", "memory");
219 
220 	return ccode;
221 }
222 
223 int rsch(struct subchannel_id schid)
224 {
225 	int ccode;
226 
227 	ccode = __rsch(schid);
228 	trace_s390_cio_rsch(schid, ccode);
229 
230 	return ccode;
231 }
232 
233 static inline int __hsch(struct subchannel_id schid)
234 {
235 	register struct subchannel_id reg1 asm("1") = schid;
236 	int ccode;
237 
238 	asm volatile(
239 		"	hsch\n"
240 		"	ipm	%0\n"
241 		"	srl	%0,28"
242 		: "=d" (ccode)
243 		: "d" (reg1)
244 		: "cc");
245 	return ccode;
246 }
247 
248 int hsch(struct subchannel_id schid)
249 {
250 	int ccode;
251 
252 	ccode = __hsch(schid);
253 	trace_s390_cio_hsch(schid, ccode);
254 
255 	return ccode;
256 }
257 
258 static inline int __xsch(struct subchannel_id schid)
259 {
260 	register struct subchannel_id reg1 asm("1") = schid;
261 	int ccode;
262 
263 	asm volatile(
264 		"	xsch\n"
265 		"	ipm	%0\n"
266 		"	srl	%0,28"
267 		: "=d" (ccode)
268 		: "d" (reg1)
269 		: "cc");
270 	return ccode;
271 }
272 
273 int xsch(struct subchannel_id schid)
274 {
275 	int ccode;
276 
277 	ccode = __xsch(schid);
278 	trace_s390_cio_xsch(schid, ccode);
279 
280 	return ccode;
281 }
282 
283 int stcrw(struct crw *crw)
284 {
285 	int ccode;
286 
287 	asm volatile(
288 		"	stcrw	0(%2)\n"
289 		"	ipm	%0\n"
290 		"	srl	%0,28\n"
291 		: "=d" (ccode), "=m" (*crw)
292 		: "a" (crw)
293 		: "cc");
294 	trace_s390_cio_stcrw(crw, ccode);
295 
296 	return ccode;
297 }
298