ioasm.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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 = -EIO;
  137. asm volatile(
  138. " .insn rre,0xb25f0000,%2,0\n"
  139. "0: ipm %0\n"
  140. " srl %0,28\n"
  141. "1:\n"
  142. EX_TABLE(0b, 1b)
  143. : "+d" (cc), "=m" (*(addr_type *) chsc_area)
  144. : "d" (chsc_area), "m" (*(addr_type *) chsc_area)
  145. : "cc");
  146. trace_s390_cio_chsc(chsc_area, cc);
  147. return cc;
  148. }
  149. EXPORT_SYMBOL(chsc);
  150. static inline int __rchp(struct chp_id chpid)
  151. {
  152. register struct chp_id reg1 asm ("1") = chpid;
  153. int ccode;
  154. asm volatile(
  155. " lr 1,%1\n"
  156. " rchp\n"
  157. " ipm %0\n"
  158. " srl %0,28"
  159. : "=d" (ccode) : "d" (reg1) : "cc");
  160. return ccode;
  161. }
  162. int rchp(struct chp_id chpid)
  163. {
  164. int ccode;
  165. ccode = __rchp(chpid);
  166. trace_s390_cio_rchp(chpid, ccode);
  167. return ccode;
  168. }
  169. static inline int __rsch(struct subchannel_id schid)
  170. {
  171. register struct subchannel_id reg1 asm("1") = schid;
  172. int ccode;
  173. asm volatile(
  174. " rsch\n"
  175. " ipm %0\n"
  176. " srl %0,28"
  177. : "=d" (ccode)
  178. : "d" (reg1)
  179. : "cc", "memory");
  180. return ccode;
  181. }
  182. int rsch(struct subchannel_id schid)
  183. {
  184. int ccode;
  185. ccode = __rsch(schid);
  186. trace_s390_cio_rsch(schid, ccode);
  187. return ccode;
  188. }
  189. static inline int __hsch(struct subchannel_id schid)
  190. {
  191. register struct subchannel_id reg1 asm("1") = schid;
  192. int ccode;
  193. asm volatile(
  194. " hsch\n"
  195. " ipm %0\n"
  196. " srl %0,28"
  197. : "=d" (ccode)
  198. : "d" (reg1)
  199. : "cc");
  200. return ccode;
  201. }
  202. int hsch(struct subchannel_id schid)
  203. {
  204. int ccode;
  205. ccode = __hsch(schid);
  206. trace_s390_cio_hsch(schid, ccode);
  207. return ccode;
  208. }
  209. static inline int __xsch(struct subchannel_id schid)
  210. {
  211. register struct subchannel_id reg1 asm("1") = schid;
  212. int ccode;
  213. asm volatile(
  214. " xsch\n"
  215. " ipm %0\n"
  216. " srl %0,28"
  217. : "=d" (ccode)
  218. : "d" (reg1)
  219. : "cc");
  220. return ccode;
  221. }
  222. int xsch(struct subchannel_id schid)
  223. {
  224. int ccode;
  225. ccode = __xsch(schid);
  226. trace_s390_cio_xsch(schid, ccode);
  227. return ccode;
  228. }
  229. int stcrw(struct crw *crw)
  230. {
  231. int ccode;
  232. asm volatile(
  233. " stcrw 0(%2)\n"
  234. " ipm %0\n"
  235. " srl %0,28\n"
  236. : "=d" (ccode), "=m" (*crw)
  237. : "a" (crw)
  238. : "cc");
  239. trace_s390_cio_stcrw(crw, ccode);
  240. return ccode;
  241. }