ioasm.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * Channel subsystem I/O instructions.
  3. */
  4. #include <linux/export.h>
  5. #include <asm/chpid.h>
  6. #include <asm/schid.h>
  7. #include <asm/crw.h>
  8. #include "ioasm.h"
  9. #include "orb.h"
  10. #include "cio.h"
  11. static inline int __stsch(struct subchannel_id schid, struct schib *addr)
  12. {
  13. register struct subchannel_id reg1 asm ("1") = schid;
  14. int ccode = -EIO;
  15. asm volatile(
  16. " stsch 0(%3)\n"
  17. "0: ipm %0\n"
  18. " srl %0,28\n"
  19. "1:\n"
  20. EX_TABLE(0b, 1b)
  21. : "+d" (ccode), "=m" (*addr)
  22. : "d" (reg1), "a" (addr)
  23. : "cc");
  24. return ccode;
  25. }
  26. int stsch(struct subchannel_id schid, struct schib *addr)
  27. {
  28. int ccode;
  29. ccode = __stsch(schid, addr);
  30. trace_s390_cio_stsch(schid, addr, ccode);
  31. return ccode;
  32. }
  33. EXPORT_SYMBOL(stsch);
  34. static inline int __msch(struct subchannel_id schid, struct schib *addr)
  35. {
  36. register struct subchannel_id reg1 asm ("1") = schid;
  37. int ccode = -EIO;
  38. asm volatile(
  39. " msch 0(%2)\n"
  40. "0: ipm %0\n"
  41. " srl %0,28\n"
  42. "1:\n"
  43. EX_TABLE(0b, 1b)
  44. : "+d" (ccode)
  45. : "d" (reg1), "a" (addr), "m" (*addr)
  46. : "cc");
  47. return ccode;
  48. }
  49. int msch(struct subchannel_id schid, struct schib *addr)
  50. {
  51. int ccode;
  52. ccode = __msch(schid, addr);
  53. trace_s390_cio_msch(schid, addr, ccode);
  54. return ccode;
  55. }
  56. static inline int __tsch(struct subchannel_id schid, struct irb *addr)
  57. {
  58. register struct subchannel_id reg1 asm ("1") = schid;
  59. int ccode;
  60. asm volatile(
  61. " tsch 0(%3)\n"
  62. " ipm %0\n"
  63. " srl %0,28"
  64. : "=d" (ccode), "=m" (*addr)
  65. : "d" (reg1), "a" (addr)
  66. : "cc");
  67. return ccode;
  68. }
  69. int tsch(struct subchannel_id schid, struct irb *addr)
  70. {
  71. int ccode;
  72. ccode = __tsch(schid, addr);
  73. trace_s390_cio_tsch(schid, addr, ccode);
  74. return ccode;
  75. }
  76. static inline int __ssch(struct subchannel_id schid, union orb *addr)
  77. {
  78. register struct subchannel_id reg1 asm("1") = schid;
  79. int ccode = -EIO;
  80. asm volatile(
  81. " ssch 0(%2)\n"
  82. "0: ipm %0\n"
  83. " srl %0,28\n"
  84. "1:\n"
  85. EX_TABLE(0b, 1b)
  86. : "+d" (ccode)
  87. : "d" (reg1), "a" (addr), "m" (*addr)
  88. : "cc", "memory");
  89. return ccode;
  90. }
  91. int ssch(struct subchannel_id schid, union orb *addr)
  92. {
  93. int ccode;
  94. ccode = __ssch(schid, addr);
  95. trace_s390_cio_ssch(schid, addr, ccode);
  96. return ccode;
  97. }
  98. EXPORT_SYMBOL(ssch);
  99. static inline int __csch(struct subchannel_id schid)
  100. {
  101. register struct subchannel_id reg1 asm("1") = schid;
  102. int ccode;
  103. asm volatile(
  104. " csch\n"
  105. " ipm %0\n"
  106. " srl %0,28"
  107. : "=d" (ccode)
  108. : "d" (reg1)
  109. : "cc");
  110. return ccode;
  111. }
  112. int csch(struct subchannel_id schid)
  113. {
  114. int ccode;
  115. ccode = __csch(schid);
  116. trace_s390_cio_csch(schid, ccode);
  117. return ccode;
  118. }
  119. EXPORT_SYMBOL(csch);
  120. int tpi(struct tpi_info *addr)
  121. {
  122. int ccode;
  123. asm volatile(
  124. " tpi 0(%2)\n"
  125. " ipm %0\n"
  126. " srl %0,28"
  127. : "=d" (ccode), "=m" (*addr)
  128. : "a" (addr)
  129. : "cc");
  130. trace_s390_cio_tpi(addr, ccode);
  131. return ccode;
  132. }
  133. int chsc(void *chsc_area)
  134. {
  135. typedef struct { char _[4096]; } addr_type;
  136. int cc;
  137. asm volatile(
  138. " .insn rre,0xb25f0000,%2,0\n"
  139. " ipm %0\n"
  140. " srl %0,28\n"
  141. : "=d" (cc), "=m" (*(addr_type *) chsc_area)
  142. : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
  143. : "cc");
  144. trace_s390_cio_chsc(chsc_area, cc);
  145. return cc;
  146. }
  147. EXPORT_SYMBOL(chsc);
  148. static inline int __rchp(struct chp_id chpid)
  149. {
  150. register struct chp_id reg1 asm ("1") = chpid;
  151. int ccode;
  152. asm volatile(
  153. " lr 1,%1\n"
  154. " rchp\n"
  155. " ipm %0\n"
  156. " srl %0,28"
  157. : "=d" (ccode) : "d" (reg1) : "cc");
  158. return ccode;
  159. }
  160. int rchp(struct chp_id chpid)
  161. {
  162. int ccode;
  163. ccode = __rchp(chpid);
  164. trace_s390_cio_rchp(chpid, ccode);
  165. return ccode;
  166. }
  167. static inline int __rsch(struct subchannel_id schid)
  168. {
  169. register struct subchannel_id reg1 asm("1") = schid;
  170. int ccode;
  171. asm volatile(
  172. " rsch\n"
  173. " ipm %0\n"
  174. " srl %0,28"
  175. : "=d" (ccode)
  176. : "d" (reg1)
  177. : "cc", "memory");
  178. return ccode;
  179. }
  180. int rsch(struct subchannel_id schid)
  181. {
  182. int ccode;
  183. ccode = __rsch(schid);
  184. trace_s390_cio_rsch(schid, ccode);
  185. return ccode;
  186. }
  187. static inline int __hsch(struct subchannel_id schid)
  188. {
  189. register struct subchannel_id reg1 asm("1") = schid;
  190. int ccode;
  191. asm volatile(
  192. " hsch\n"
  193. " ipm %0\n"
  194. " srl %0,28"
  195. : "=d" (ccode)
  196. : "d" (reg1)
  197. : "cc");
  198. return ccode;
  199. }
  200. int hsch(struct subchannel_id schid)
  201. {
  202. int ccode;
  203. ccode = __hsch(schid);
  204. trace_s390_cio_hsch(schid, ccode);
  205. return ccode;
  206. }
  207. static inline int __xsch(struct subchannel_id schid)
  208. {
  209. register struct subchannel_id reg1 asm("1") = schid;
  210. int ccode;
  211. asm volatile(
  212. " xsch\n"
  213. " ipm %0\n"
  214. " srl %0,28"
  215. : "=d" (ccode)
  216. : "d" (reg1)
  217. : "cc");
  218. return ccode;
  219. }
  220. int xsch(struct subchannel_id schid)
  221. {
  222. int ccode;
  223. ccode = __xsch(schid);
  224. trace_s390_cio_xsch(schid, ccode);
  225. return ccode;
  226. }
  227. int stcrw(struct crw *crw)
  228. {
  229. int ccode;
  230. asm volatile(
  231. " stcrw 0(%2)\n"
  232. " ipm %0\n"
  233. " srl %0,28\n"
  234. : "=d" (ccode), "=m" (*crw)
  235. : "a" (crw)
  236. : "cc");
  237. trace_s390_cio_stcrw(crw, ccode);
  238. return ccode;
  239. }