xref: /linux/drivers/s390/cio/ioasm.c (revision 82045dd85566d87128dcc66277cf1177d9930a4a)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
211b64c8aSPeter Oberparleiter /*
311b64c8aSPeter Oberparleiter  * Channel subsystem I/O instructions.
411b64c8aSPeter Oberparleiter  */
511b64c8aSPeter Oberparleiter 
611b64c8aSPeter Oberparleiter #include <linux/export.h>
711b64c8aSPeter Oberparleiter 
811b64c8aSPeter Oberparleiter #include <asm/chpid.h>
911b64c8aSPeter Oberparleiter #include <asm/schid.h>
1011b64c8aSPeter Oberparleiter #include <asm/crw.h>
1111b64c8aSPeter Oberparleiter 
1211b64c8aSPeter Oberparleiter #include "ioasm.h"
1311b64c8aSPeter Oberparleiter #include "orb.h"
1411b64c8aSPeter Oberparleiter #include "cio.h"
1511b64c8aSPeter Oberparleiter 
16a4d9b97cSHeiko Carstens static inline int __stsch(struct subchannel_id schid, struct schib *addr)
1711b64c8aSPeter Oberparleiter {
1811b64c8aSPeter Oberparleiter 	register struct subchannel_id reg1 asm ("1") = schid;
1911b64c8aSPeter Oberparleiter 	int ccode = -EIO;
2011b64c8aSPeter Oberparleiter 
2111b64c8aSPeter Oberparleiter 	asm volatile(
2211b64c8aSPeter Oberparleiter 		"	stsch	0(%3)\n"
2311b64c8aSPeter Oberparleiter 		"0:	ipm	%0\n"
2411b64c8aSPeter Oberparleiter 		"	srl	%0,28\n"
2511b64c8aSPeter Oberparleiter 		"1:\n"
2611b64c8aSPeter Oberparleiter 		EX_TABLE(0b, 1b)
2711b64c8aSPeter Oberparleiter 		: "+d" (ccode), "=m" (*addr)
2811b64c8aSPeter Oberparleiter 		: "d" (reg1), "a" (addr)
2911b64c8aSPeter Oberparleiter 		: "cc");
30a4d9b97cSHeiko Carstens 	return ccode;
31a4d9b97cSHeiko Carstens }
32a4d9b97cSHeiko Carstens 
33a4d9b97cSHeiko Carstens int stsch(struct subchannel_id schid, struct schib *addr)
34a4d9b97cSHeiko Carstens {
35a4d9b97cSHeiko Carstens 	int ccode;
36a4d9b97cSHeiko Carstens 
37a4d9b97cSHeiko Carstens 	ccode = __stsch(schid, addr);
3811b64c8aSPeter Oberparleiter 	trace_s390_cio_stsch(schid, addr, ccode);
3911b64c8aSPeter Oberparleiter 
4011b64c8aSPeter Oberparleiter 	return ccode;
4111b64c8aSPeter Oberparleiter }
4211b64c8aSPeter Oberparleiter EXPORT_SYMBOL(stsch);
4311b64c8aSPeter Oberparleiter 
44a4d9b97cSHeiko Carstens static inline int __msch(struct subchannel_id schid, struct schib *addr)
4511b64c8aSPeter Oberparleiter {
4611b64c8aSPeter Oberparleiter 	register struct subchannel_id reg1 asm ("1") = schid;
4711b64c8aSPeter Oberparleiter 	int ccode = -EIO;
4811b64c8aSPeter Oberparleiter 
4911b64c8aSPeter Oberparleiter 	asm volatile(
5011b64c8aSPeter Oberparleiter 		"	msch	0(%2)\n"
5111b64c8aSPeter Oberparleiter 		"0:	ipm	%0\n"
5211b64c8aSPeter Oberparleiter 		"	srl	%0,28\n"
5311b64c8aSPeter Oberparleiter 		"1:\n"
5411b64c8aSPeter Oberparleiter 		EX_TABLE(0b, 1b)
5511b64c8aSPeter Oberparleiter 		: "+d" (ccode)
5611b64c8aSPeter Oberparleiter 		: "d" (reg1), "a" (addr), "m" (*addr)
5711b64c8aSPeter Oberparleiter 		: "cc");
58a4d9b97cSHeiko Carstens 	return ccode;
59a4d9b97cSHeiko Carstens }
60a4d9b97cSHeiko Carstens 
61a4d9b97cSHeiko Carstens int msch(struct subchannel_id schid, struct schib *addr)
62a4d9b97cSHeiko Carstens {
63a4d9b97cSHeiko Carstens 	int ccode;
64a4d9b97cSHeiko Carstens 
65a4d9b97cSHeiko Carstens 	ccode = __msch(schid, addr);
6611b64c8aSPeter Oberparleiter 	trace_s390_cio_msch(schid, addr, ccode);
6711b64c8aSPeter Oberparleiter 
6811b64c8aSPeter Oberparleiter 	return ccode;
6911b64c8aSPeter Oberparleiter }
7011b64c8aSPeter Oberparleiter 
71a4d9b97cSHeiko Carstens static inline int __tsch(struct subchannel_id schid, struct irb *addr)
7211b64c8aSPeter Oberparleiter {
7311b64c8aSPeter Oberparleiter 	register struct subchannel_id reg1 asm ("1") = schid;
7411b64c8aSPeter Oberparleiter 	int ccode;
7511b64c8aSPeter Oberparleiter 
7611b64c8aSPeter Oberparleiter 	asm volatile(
7711b64c8aSPeter Oberparleiter 		"	tsch	0(%3)\n"
7811b64c8aSPeter Oberparleiter 		"	ipm	%0\n"
7911b64c8aSPeter Oberparleiter 		"	srl	%0,28"
8011b64c8aSPeter Oberparleiter 		: "=d" (ccode), "=m" (*addr)
8111b64c8aSPeter Oberparleiter 		: "d" (reg1), "a" (addr)
8211b64c8aSPeter Oberparleiter 		: "cc");
83a4d9b97cSHeiko Carstens 	return ccode;
84a4d9b97cSHeiko Carstens }
85a4d9b97cSHeiko Carstens 
86a4d9b97cSHeiko Carstens int tsch(struct subchannel_id schid, struct irb *addr)
87a4d9b97cSHeiko Carstens {
88a4d9b97cSHeiko Carstens 	int ccode;
89a4d9b97cSHeiko Carstens 
90a4d9b97cSHeiko Carstens 	ccode = __tsch(schid, addr);
9111b64c8aSPeter Oberparleiter 	trace_s390_cio_tsch(schid, addr, ccode);
9211b64c8aSPeter Oberparleiter 
9311b64c8aSPeter Oberparleiter 	return ccode;
9411b64c8aSPeter Oberparleiter }
9511b64c8aSPeter Oberparleiter 
96a4d9b97cSHeiko Carstens static inline int __ssch(struct subchannel_id schid, union orb *addr)
9711b64c8aSPeter Oberparleiter {
9811b64c8aSPeter Oberparleiter 	register struct subchannel_id reg1 asm("1") = schid;
9911b64c8aSPeter Oberparleiter 	int ccode = -EIO;
10011b64c8aSPeter Oberparleiter 
10111b64c8aSPeter Oberparleiter 	asm volatile(
10211b64c8aSPeter Oberparleiter 		"	ssch	0(%2)\n"
10311b64c8aSPeter Oberparleiter 		"0:	ipm	%0\n"
10411b64c8aSPeter Oberparleiter 		"	srl	%0,28\n"
10511b64c8aSPeter Oberparleiter 		"1:\n"
10611b64c8aSPeter Oberparleiter 		EX_TABLE(0b, 1b)
10711b64c8aSPeter Oberparleiter 		: "+d" (ccode)
10811b64c8aSPeter Oberparleiter 		: "d" (reg1), "a" (addr), "m" (*addr)
10911b64c8aSPeter Oberparleiter 		: "cc", "memory");
110a4d9b97cSHeiko Carstens 	return ccode;
111a4d9b97cSHeiko Carstens }
112a4d9b97cSHeiko Carstens 
113a4d9b97cSHeiko Carstens int ssch(struct subchannel_id schid, union orb *addr)
114a4d9b97cSHeiko Carstens {
115a4d9b97cSHeiko Carstens 	int ccode;
116a4d9b97cSHeiko Carstens 
117a4d9b97cSHeiko Carstens 	ccode = __ssch(schid, addr);
11811b64c8aSPeter Oberparleiter 	trace_s390_cio_ssch(schid, addr, ccode);
11911b64c8aSPeter Oberparleiter 
12011b64c8aSPeter Oberparleiter 	return ccode;
12111b64c8aSPeter Oberparleiter }
12211b64c8aSPeter Oberparleiter EXPORT_SYMBOL(ssch);
12311b64c8aSPeter Oberparleiter 
124a4d9b97cSHeiko Carstens static inline int __csch(struct subchannel_id schid)
12511b64c8aSPeter Oberparleiter {
12611b64c8aSPeter Oberparleiter 	register struct subchannel_id reg1 asm("1") = schid;
12711b64c8aSPeter Oberparleiter 	int ccode;
12811b64c8aSPeter Oberparleiter 
12911b64c8aSPeter Oberparleiter 	asm volatile(
13011b64c8aSPeter Oberparleiter 		"	csch\n"
13111b64c8aSPeter Oberparleiter 		"	ipm	%0\n"
13211b64c8aSPeter Oberparleiter 		"	srl	%0,28"
13311b64c8aSPeter Oberparleiter 		: "=d" (ccode)
13411b64c8aSPeter Oberparleiter 		: "d" (reg1)
13511b64c8aSPeter Oberparleiter 		: "cc");
136a4d9b97cSHeiko Carstens 	return ccode;
137a4d9b97cSHeiko Carstens }
138a4d9b97cSHeiko Carstens 
139a4d9b97cSHeiko Carstens int csch(struct subchannel_id schid)
140a4d9b97cSHeiko Carstens {
141a4d9b97cSHeiko Carstens 	int ccode;
142a4d9b97cSHeiko Carstens 
143a4d9b97cSHeiko Carstens 	ccode = __csch(schid);
14411b64c8aSPeter Oberparleiter 	trace_s390_cio_csch(schid, ccode);
14511b64c8aSPeter Oberparleiter 
14611b64c8aSPeter Oberparleiter 	return ccode;
14711b64c8aSPeter Oberparleiter }
14811b64c8aSPeter Oberparleiter EXPORT_SYMBOL(csch);
14911b64c8aSPeter Oberparleiter 
15011b64c8aSPeter Oberparleiter int tpi(struct tpi_info *addr)
15111b64c8aSPeter Oberparleiter {
15211b64c8aSPeter Oberparleiter 	int ccode;
15311b64c8aSPeter Oberparleiter 
15411b64c8aSPeter Oberparleiter 	asm volatile(
15511b64c8aSPeter Oberparleiter 		"	tpi	0(%2)\n"
15611b64c8aSPeter Oberparleiter 		"	ipm	%0\n"
15711b64c8aSPeter Oberparleiter 		"	srl	%0,28"
15811b64c8aSPeter Oberparleiter 		: "=d" (ccode), "=m" (*addr)
15911b64c8aSPeter Oberparleiter 		: "a" (addr)
16011b64c8aSPeter Oberparleiter 		: "cc");
16111b64c8aSPeter Oberparleiter 	trace_s390_cio_tpi(addr, ccode);
16211b64c8aSPeter Oberparleiter 
16311b64c8aSPeter Oberparleiter 	return ccode;
16411b64c8aSPeter Oberparleiter }
16511b64c8aSPeter Oberparleiter 
16611b64c8aSPeter Oberparleiter int chsc(void *chsc_area)
16711b64c8aSPeter Oberparleiter {
16811b64c8aSPeter Oberparleiter 	typedef struct { char _[4096]; } addr_type;
16977759137SPeter Oberparleiter 	int cc = -EIO;
17011b64c8aSPeter Oberparleiter 
17111b64c8aSPeter Oberparleiter 	asm volatile(
17211b64c8aSPeter Oberparleiter 		"	.insn	rre,0xb25f0000,%2,0\n"
17377759137SPeter Oberparleiter 		"0:	ipm	%0\n"
17411b64c8aSPeter Oberparleiter 		"	srl	%0,28\n"
17577759137SPeter Oberparleiter 		"1:\n"
17677759137SPeter Oberparleiter 		EX_TABLE(0b, 1b)
17777759137SPeter Oberparleiter 		: "+d" (cc), "=m" (*(addr_type *) chsc_area)
17811b64c8aSPeter Oberparleiter 		: "d" (chsc_area), "m" (*(addr_type *) chsc_area)
17911b64c8aSPeter Oberparleiter 		: "cc");
18011b64c8aSPeter Oberparleiter 	trace_s390_cio_chsc(chsc_area, cc);
18111b64c8aSPeter Oberparleiter 
18211b64c8aSPeter Oberparleiter 	return cc;
18311b64c8aSPeter Oberparleiter }
18411b64c8aSPeter Oberparleiter EXPORT_SYMBOL(chsc);
18511b64c8aSPeter Oberparleiter 
186a4d9b97cSHeiko Carstens static inline int __rsch(struct subchannel_id schid)
18711b64c8aSPeter Oberparleiter {
18811b64c8aSPeter Oberparleiter 	register struct subchannel_id reg1 asm("1") = schid;
18911b64c8aSPeter Oberparleiter 	int ccode;
19011b64c8aSPeter Oberparleiter 
19111b64c8aSPeter Oberparleiter 	asm volatile(
19211b64c8aSPeter Oberparleiter 		"	rsch\n"
19311b64c8aSPeter Oberparleiter 		"	ipm	%0\n"
19411b64c8aSPeter Oberparleiter 		"	srl	%0,28"
19511b64c8aSPeter Oberparleiter 		: "=d" (ccode)
19611b64c8aSPeter Oberparleiter 		: "d" (reg1)
19711b64c8aSPeter Oberparleiter 		: "cc", "memory");
198a4d9b97cSHeiko Carstens 
199a4d9b97cSHeiko Carstens 	return ccode;
200a4d9b97cSHeiko Carstens }
201a4d9b97cSHeiko Carstens 
202a4d9b97cSHeiko Carstens int rsch(struct subchannel_id schid)
203a4d9b97cSHeiko Carstens {
204a4d9b97cSHeiko Carstens 	int ccode;
205a4d9b97cSHeiko Carstens 
206a4d9b97cSHeiko Carstens 	ccode = __rsch(schid);
20711b64c8aSPeter Oberparleiter 	trace_s390_cio_rsch(schid, ccode);
20811b64c8aSPeter Oberparleiter 
20911b64c8aSPeter Oberparleiter 	return ccode;
21011b64c8aSPeter Oberparleiter }
21111b64c8aSPeter Oberparleiter 
212a4d9b97cSHeiko Carstens static inline int __hsch(struct subchannel_id schid)
21311b64c8aSPeter Oberparleiter {
21411b64c8aSPeter Oberparleiter 	register struct subchannel_id reg1 asm("1") = schid;
21511b64c8aSPeter Oberparleiter 	int ccode;
21611b64c8aSPeter Oberparleiter 
21711b64c8aSPeter Oberparleiter 	asm volatile(
21811b64c8aSPeter Oberparleiter 		"	hsch\n"
21911b64c8aSPeter Oberparleiter 		"	ipm	%0\n"
22011b64c8aSPeter Oberparleiter 		"	srl	%0,28"
22111b64c8aSPeter Oberparleiter 		: "=d" (ccode)
22211b64c8aSPeter Oberparleiter 		: "d" (reg1)
22311b64c8aSPeter Oberparleiter 		: "cc");
224a4d9b97cSHeiko Carstens 	return ccode;
225a4d9b97cSHeiko Carstens }
226a4d9b97cSHeiko Carstens 
227a4d9b97cSHeiko Carstens int hsch(struct subchannel_id schid)
228a4d9b97cSHeiko Carstens {
229a4d9b97cSHeiko Carstens 	int ccode;
230a4d9b97cSHeiko Carstens 
231a4d9b97cSHeiko Carstens 	ccode = __hsch(schid);
23211b64c8aSPeter Oberparleiter 	trace_s390_cio_hsch(schid, ccode);
23311b64c8aSPeter Oberparleiter 
23411b64c8aSPeter Oberparleiter 	return ccode;
23511b64c8aSPeter Oberparleiter }
236*b0940857SCornelia Huck EXPORT_SYMBOL(hsch);
23711b64c8aSPeter Oberparleiter 
238a4d9b97cSHeiko Carstens static inline int __xsch(struct subchannel_id schid)
23911b64c8aSPeter Oberparleiter {
24011b64c8aSPeter Oberparleiter 	register struct subchannel_id reg1 asm("1") = schid;
24111b64c8aSPeter Oberparleiter 	int ccode;
24211b64c8aSPeter Oberparleiter 
24311b64c8aSPeter Oberparleiter 	asm volatile(
24411b64c8aSPeter Oberparleiter 		"	xsch\n"
24511b64c8aSPeter Oberparleiter 		"	ipm	%0\n"
24611b64c8aSPeter Oberparleiter 		"	srl	%0,28"
24711b64c8aSPeter Oberparleiter 		: "=d" (ccode)
24811b64c8aSPeter Oberparleiter 		: "d" (reg1)
24911b64c8aSPeter Oberparleiter 		: "cc");
250a4d9b97cSHeiko Carstens 	return ccode;
251a4d9b97cSHeiko Carstens }
252a4d9b97cSHeiko Carstens 
253a4d9b97cSHeiko Carstens int xsch(struct subchannel_id schid)
254a4d9b97cSHeiko Carstens {
255a4d9b97cSHeiko Carstens 	int ccode;
256a4d9b97cSHeiko Carstens 
257a4d9b97cSHeiko Carstens 	ccode = __xsch(schid);
25811b64c8aSPeter Oberparleiter 	trace_s390_cio_xsch(schid, ccode);
25911b64c8aSPeter Oberparleiter 
26011b64c8aSPeter Oberparleiter 	return ccode;
26111b64c8aSPeter Oberparleiter }
26211b64c8aSPeter Oberparleiter 
26311b64c8aSPeter Oberparleiter int stcrw(struct crw *crw)
26411b64c8aSPeter Oberparleiter {
26511b64c8aSPeter Oberparleiter 	int ccode;
26611b64c8aSPeter Oberparleiter 
26711b64c8aSPeter Oberparleiter 	asm volatile(
26811b64c8aSPeter Oberparleiter 		"	stcrw	0(%2)\n"
26911b64c8aSPeter Oberparleiter 		"	ipm	%0\n"
27011b64c8aSPeter Oberparleiter 		"	srl	%0,28\n"
27111b64c8aSPeter Oberparleiter 		: "=d" (ccode), "=m" (*crw)
27211b64c8aSPeter Oberparleiter 		: "a" (crw)
27311b64c8aSPeter Oberparleiter 		: "cc");
27411b64c8aSPeter Oberparleiter 	trace_s390_cio_stcrw(crw, ccode);
27511b64c8aSPeter Oberparleiter 
27611b64c8aSPeter Oberparleiter 	return ccode;
27711b64c8aSPeter Oberparleiter }
278