ioasm.c 4.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*
 * Channel subsystem I/O instructions.
 */

#include <linux/export.h>

#include <asm/chpid.h>
#include <asm/schid.h>
#include <asm/crw.h>

#include "ioasm.h"
#include "orb.h"
#include "cio.h"

15
static inline int __stsch(struct subchannel_id schid, struct schib *addr)
16 17 18 19 20 21 22 23 24 25 26 27 28
{
	register struct subchannel_id reg1 asm ("1") = schid;
	int ccode = -EIO;

	asm volatile(
		"	stsch	0(%3)\n"
		"0:	ipm	%0\n"
		"	srl	%0,28\n"
		"1:\n"
		EX_TABLE(0b, 1b)
		: "+d" (ccode), "=m" (*addr)
		: "d" (reg1), "a" (addr)
		: "cc");
29 30 31 32 33 34 35 36
	return ccode;
}

int stsch(struct subchannel_id schid, struct schib *addr)
{
	int ccode;

	ccode = __stsch(schid, addr);
37 38 39 40 41 42
	trace_s390_cio_stsch(schid, addr, ccode);

	return ccode;
}
EXPORT_SYMBOL(stsch);

43
static inline int __msch(struct subchannel_id schid, struct schib *addr)
44 45 46 47 48 49 50 51 52 53 54 55 56
{
	register struct subchannel_id reg1 asm ("1") = schid;
	int ccode = -EIO;

	asm volatile(
		"	msch	0(%2)\n"
		"0:	ipm	%0\n"
		"	srl	%0,28\n"
		"1:\n"
		EX_TABLE(0b, 1b)
		: "+d" (ccode)
		: "d" (reg1), "a" (addr), "m" (*addr)
		: "cc");
57 58 59 60 61 62 63 64
	return ccode;
}

int msch(struct subchannel_id schid, struct schib *addr)
{
	int ccode;

	ccode = __msch(schid, addr);
65 66 67 68 69
	trace_s390_cio_msch(schid, addr, ccode);

	return ccode;
}

70
static inline int __tsch(struct subchannel_id schid, struct irb *addr)
71 72 73 74 75 76 77 78 79 80 81
{
	register struct subchannel_id reg1 asm ("1") = schid;
	int ccode;

	asm volatile(
		"	tsch	0(%3)\n"
		"	ipm	%0\n"
		"	srl	%0,28"
		: "=d" (ccode), "=m" (*addr)
		: "d" (reg1), "a" (addr)
		: "cc");
82 83 84 85 86 87 88 89
	return ccode;
}

int tsch(struct subchannel_id schid, struct irb *addr)
{
	int ccode;

	ccode = __tsch(schid, addr);
90 91 92 93 94
	trace_s390_cio_tsch(schid, addr, ccode);

	return ccode;
}

95
static inline int __ssch(struct subchannel_id schid, union orb *addr)
96 97 98 99 100 101 102 103 104 105 106 107 108
{
	register struct subchannel_id reg1 asm("1") = schid;
	int ccode = -EIO;

	asm volatile(
		"	ssch	0(%2)\n"
		"0:	ipm	%0\n"
		"	srl	%0,28\n"
		"1:\n"
		EX_TABLE(0b, 1b)
		: "+d" (ccode)
		: "d" (reg1), "a" (addr), "m" (*addr)
		: "cc", "memory");
109 110 111 112 113 114 115 116
	return ccode;
}

int ssch(struct subchannel_id schid, union orb *addr)
{
	int ccode;

	ccode = __ssch(schid, addr);
117 118 119 120 121 122
	trace_s390_cio_ssch(schid, addr, ccode);

	return ccode;
}
EXPORT_SYMBOL(ssch);

123
static inline int __csch(struct subchannel_id schid)
124 125 126 127 128 129 130 131 132 133 134
{
	register struct subchannel_id reg1 asm("1") = schid;
	int ccode;

	asm volatile(
		"	csch\n"
		"	ipm	%0\n"
		"	srl	%0,28"
		: "=d" (ccode)
		: "d" (reg1)
		: "cc");
135 136 137 138 139 140 141 142
	return ccode;
}

int csch(struct subchannel_id schid)
{
	int ccode;

	ccode = __csch(schid);
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
	trace_s390_cio_csch(schid, ccode);

	return ccode;
}
EXPORT_SYMBOL(csch);

int tpi(struct tpi_info *addr)
{
	int ccode;

	asm volatile(
		"	tpi	0(%2)\n"
		"	ipm	%0\n"
		"	srl	%0,28"
		: "=d" (ccode), "=m" (*addr)
		: "a" (addr)
		: "cc");
	trace_s390_cio_tpi(addr, ccode);

	return ccode;
}

int chsc(void *chsc_area)
{
	typedef struct { char _[4096]; } addr_type;
168
	int cc = -EIO;
169 170 171

	asm volatile(
		"	.insn	rre,0xb25f0000,%2,0\n"
172
		"0:	ipm	%0\n"
173
		"	srl	%0,28\n"
174 175 176
		"1:\n"
		EX_TABLE(0b, 1b)
		: "+d" (cc), "=m" (*(addr_type *) chsc_area)
177 178 179 180 181 182 183 184
		: "d" (chsc_area), "m" (*(addr_type *) chsc_area)
		: "cc");
	trace_s390_cio_chsc(chsc_area, cc);

	return cc;
}
EXPORT_SYMBOL(chsc);

185
static inline int __rchp(struct chp_id chpid)
186 187 188 189 190 191 192 193 194 195
{
	register struct chp_id reg1 asm ("1") = chpid;
	int ccode;

	asm volatile(
		"	lr	1,%1\n"
		"	rchp\n"
		"	ipm	%0\n"
		"	srl	%0,28"
		: "=d" (ccode) : "d" (reg1) : "cc");
196 197 198 199 200 201 202 203
	return ccode;
}

int rchp(struct chp_id chpid)
{
	int ccode;

	ccode = __rchp(chpid);
204 205 206 207 208
	trace_s390_cio_rchp(chpid, ccode);

	return ccode;
}

209
static inline int __rsch(struct subchannel_id schid)
210 211 212 213 214 215 216 217 218 219 220
{
	register struct subchannel_id reg1 asm("1") = schid;
	int ccode;

	asm volatile(
		"	rsch\n"
		"	ipm	%0\n"
		"	srl	%0,28"
		: "=d" (ccode)
		: "d" (reg1)
		: "cc", "memory");
221 222 223 224 225 226 227 228 229

	return ccode;
}

int rsch(struct subchannel_id schid)
{
	int ccode;

	ccode = __rsch(schid);
230 231 232 233 234
	trace_s390_cio_rsch(schid, ccode);

	return ccode;
}

235
static inline int __hsch(struct subchannel_id schid)
236 237 238 239 240 241 242 243 244 245 246
{
	register struct subchannel_id reg1 asm("1") = schid;
	int ccode;

	asm volatile(
		"	hsch\n"
		"	ipm	%0\n"
		"	srl	%0,28"
		: "=d" (ccode)
		: "d" (reg1)
		: "cc");
247 248 249 250 251 252 253 254
	return ccode;
}

int hsch(struct subchannel_id schid)
{
	int ccode;

	ccode = __hsch(schid);
255 256 257 258 259
	trace_s390_cio_hsch(schid, ccode);

	return ccode;
}

260
static inline int __xsch(struct subchannel_id schid)
261 262 263 264 265 266 267 268 269 270 271
{
	register struct subchannel_id reg1 asm("1") = schid;
	int ccode;

	asm volatile(
		"	xsch\n"
		"	ipm	%0\n"
		"	srl	%0,28"
		: "=d" (ccode)
		: "d" (reg1)
		: "cc");
272 273 274 275 276 277 278 279
	return ccode;
}

int xsch(struct subchannel_id schid)
{
	int ccode;

	ccode = __xsch(schid);
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
	trace_s390_cio_xsch(schid, ccode);

	return ccode;
}

int stcrw(struct crw *crw)
{
	int ccode;

	asm volatile(
		"	stcrw	0(%2)\n"
		"	ipm	%0\n"
		"	srl	%0,28\n"
		: "=d" (ccode), "=m" (*crw)
		: "a" (crw)
		: "cc");
	trace_s390_cio_stcrw(crw, ccode);

	return ccode;
}