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