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