fcx.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Functions for assembling fcx enabled I/O control blocks.
  4. *
  5. * Copyright IBM Corp. 2008
  6. * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  7. */
  8. #include <linux/kernel.h>
  9. #include <linux/types.h>
  10. #include <linux/string.h>
  11. #include <linux/errno.h>
  12. #include <linux/err.h>
  13. #include <linux/module.h>
  14. #include <asm/fcx.h>
  15. #include "cio.h"
  16. /**
  17. * tcw_get_intrg - return pointer to associated interrogate tcw
  18. * @tcw: pointer to the original tcw
  19. *
  20. * Return a pointer to the interrogate tcw associated with the specified tcw
  21. * or %NULL if there is no associated interrogate tcw.
  22. */
  23. struct tcw *tcw_get_intrg(struct tcw *tcw)
  24. {
  25. return (struct tcw *) ((addr_t) tcw->intrg);
  26. }
  27. EXPORT_SYMBOL(tcw_get_intrg);
  28. /**
  29. * tcw_get_data - return pointer to input/output data associated with tcw
  30. * @tcw: pointer to the tcw
  31. *
  32. * Return the input or output data address specified in the tcw depending
  33. * on whether the r-bit or the w-bit is set. If neither bit is set, return
  34. * %NULL.
  35. */
  36. void *tcw_get_data(struct tcw *tcw)
  37. {
  38. if (tcw->r)
  39. return (void *) ((addr_t) tcw->input);
  40. if (tcw->w)
  41. return (void *) ((addr_t) tcw->output);
  42. return NULL;
  43. }
  44. EXPORT_SYMBOL(tcw_get_data);
  45. /**
  46. * tcw_get_tccb - return pointer to tccb associated with tcw
  47. * @tcw: pointer to the tcw
  48. *
  49. * Return pointer to the tccb associated with this tcw.
  50. */
  51. struct tccb *tcw_get_tccb(struct tcw *tcw)
  52. {
  53. return (struct tccb *) ((addr_t) tcw->tccb);
  54. }
  55. EXPORT_SYMBOL(tcw_get_tccb);
  56. /**
  57. * tcw_get_tsb - return pointer to tsb associated with tcw
  58. * @tcw: pointer to the tcw
  59. *
  60. * Return pointer to the tsb associated with this tcw.
  61. */
  62. struct tsb *tcw_get_tsb(struct tcw *tcw)
  63. {
  64. return (struct tsb *) ((addr_t) tcw->tsb);
  65. }
  66. EXPORT_SYMBOL(tcw_get_tsb);
  67. /**
  68. * tcw_init - initialize tcw data structure
  69. * @tcw: pointer to the tcw to be initialized
  70. * @r: initial value of the r-bit
  71. * @w: initial value of the w-bit
  72. *
  73. * Initialize all fields of the specified tcw data structure with zero and
  74. * fill in the format, flags, r and w fields.
  75. */
  76. void tcw_init(struct tcw *tcw, int r, int w)
  77. {
  78. memset(tcw, 0, sizeof(struct tcw));
  79. tcw->format = TCW_FORMAT_DEFAULT;
  80. tcw->flags = TCW_FLAGS_TIDAW_FORMAT(TCW_TIDAW_FORMAT_DEFAULT);
  81. if (r)
  82. tcw->r = 1;
  83. if (w)
  84. tcw->w = 1;
  85. }
  86. EXPORT_SYMBOL(tcw_init);
  87. static inline size_t tca_size(struct tccb *tccb)
  88. {
  89. return tccb->tcah.tcal - 12;
  90. }
  91. static u32 calc_dcw_count(struct tccb *tccb)
  92. {
  93. int offset;
  94. struct dcw *dcw;
  95. u32 count = 0;
  96. size_t size;
  97. size = tca_size(tccb);
  98. for (offset = 0; offset < size;) {
  99. dcw = (struct dcw *) &tccb->tca[offset];
  100. count += dcw->count;
  101. if (!(dcw->flags & DCW_FLAGS_CC))
  102. break;
  103. offset += sizeof(struct dcw) + ALIGN((int) dcw->cd_count, 4);
  104. }
  105. return count;
  106. }
  107. static u32 calc_cbc_size(struct tidaw *tidaw, int num)
  108. {
  109. int i;
  110. u32 cbc_data;
  111. u32 cbc_count = 0;
  112. u64 data_count = 0;
  113. for (i = 0; i < num; i++) {
  114. if (tidaw[i].flags & TIDAW_FLAGS_LAST)
  115. break;
  116. /* TODO: find out if padding applies to total of data
  117. * transferred or data transferred by this tidaw. Assumption:
  118. * applies to total. */
  119. data_count += tidaw[i].count;
  120. if (tidaw[i].flags & TIDAW_FLAGS_INSERT_CBC) {
  121. cbc_data = 4 + ALIGN(data_count, 4) - data_count;
  122. cbc_count += cbc_data;
  123. data_count += cbc_data;
  124. }
  125. }
  126. return cbc_count;
  127. }
  128. /**
  129. * tcw_finalize - finalize tcw length fields and tidaw list
  130. * @tcw: pointer to the tcw
  131. * @num_tidaws: the number of tidaws used to address input/output data or zero
  132. * if no tida is used
  133. *
  134. * Calculate the input-/output-count and tccbl field in the tcw, add a
  135. * tcat the tccb and terminate the data tidaw list if used.
  136. *
  137. * Note: in case input- or output-tida is used, the tidaw-list must be stored
  138. * in contiguous storage (no ttic). The tcal field in the tccb must be
  139. * up-to-date.
  140. */
  141. void tcw_finalize(struct tcw *tcw, int num_tidaws)
  142. {
  143. struct tidaw *tidaw;
  144. struct tccb *tccb;
  145. struct tccb_tcat *tcat;
  146. u32 count;
  147. /* Terminate tidaw list. */
  148. tidaw = tcw_get_data(tcw);
  149. if (num_tidaws > 0)
  150. tidaw[num_tidaws - 1].flags |= TIDAW_FLAGS_LAST;
  151. /* Add tcat to tccb. */
  152. tccb = tcw_get_tccb(tcw);
  153. tcat = (struct tccb_tcat *) &tccb->tca[tca_size(tccb)];
  154. memset(tcat, 0, sizeof(*tcat));
  155. /* Calculate tcw input/output count and tcat transport count. */
  156. count = calc_dcw_count(tccb);
  157. if (tcw->w && (tcw->flags & TCW_FLAGS_OUTPUT_TIDA))
  158. count += calc_cbc_size(tidaw, num_tidaws);
  159. if (tcw->r)
  160. tcw->input_count = count;
  161. else if (tcw->w)
  162. tcw->output_count = count;
  163. tcat->count = ALIGN(count, 4) + 4;
  164. /* Calculate tccbl. */
  165. tcw->tccbl = (sizeof(struct tccb) + tca_size(tccb) +
  166. sizeof(struct tccb_tcat) - 20) >> 2;
  167. }
  168. EXPORT_SYMBOL(tcw_finalize);
  169. /**
  170. * tcw_set_intrg - set the interrogate tcw address of a tcw
  171. * @tcw: the tcw address
  172. * @intrg_tcw: the address of the interrogate tcw
  173. *
  174. * Set the address of the interrogate tcw in the specified tcw.
  175. */
  176. void tcw_set_intrg(struct tcw *tcw, struct tcw *intrg_tcw)
  177. {
  178. tcw->intrg = (u32) ((addr_t) intrg_tcw);
  179. }
  180. EXPORT_SYMBOL(tcw_set_intrg);
  181. /**
  182. * tcw_set_data - set data address and tida flag of a tcw
  183. * @tcw: the tcw address
  184. * @data: the data address
  185. * @use_tidal: zero of the data address specifies a contiguous block of data,
  186. * non-zero if it specifies a list if tidaws.
  187. *
  188. * Set the input/output data address of a tcw (depending on the value of the
  189. * r-flag and w-flag). If @use_tidal is non-zero, the corresponding tida flag
  190. * is set as well.
  191. */
  192. void tcw_set_data(struct tcw *tcw, void *data, int use_tidal)
  193. {
  194. if (tcw->r) {
  195. tcw->input = (u64) ((addr_t) data);
  196. if (use_tidal)
  197. tcw->flags |= TCW_FLAGS_INPUT_TIDA;
  198. } else if (tcw->w) {
  199. tcw->output = (u64) ((addr_t) data);
  200. if (use_tidal)
  201. tcw->flags |= TCW_FLAGS_OUTPUT_TIDA;
  202. }
  203. }
  204. EXPORT_SYMBOL(tcw_set_data);
  205. /**
  206. * tcw_set_tccb - set tccb address of a tcw
  207. * @tcw: the tcw address
  208. * @tccb: the tccb address
  209. *
  210. * Set the address of the tccb in the specified tcw.
  211. */
  212. void tcw_set_tccb(struct tcw *tcw, struct tccb *tccb)
  213. {
  214. tcw->tccb = (u64) ((addr_t) tccb);
  215. }
  216. EXPORT_SYMBOL(tcw_set_tccb);
  217. /**
  218. * tcw_set_tsb - set tsb address of a tcw
  219. * @tcw: the tcw address
  220. * @tsb: the tsb address
  221. *
  222. * Set the address of the tsb in the specified tcw.
  223. */
  224. void tcw_set_tsb(struct tcw *tcw, struct tsb *tsb)
  225. {
  226. tcw->tsb = (u64) ((addr_t) tsb);
  227. }
  228. EXPORT_SYMBOL(tcw_set_tsb);
  229. /**
  230. * tccb_init - initialize tccb
  231. * @tccb: the tccb address
  232. * @size: the maximum size of the tccb
  233. * @sac: the service-action-code to be user
  234. *
  235. * Initialize the header of the specified tccb by resetting all values to zero
  236. * and filling in defaults for format, sac and initial tcal fields.
  237. */
  238. void tccb_init(struct tccb *tccb, size_t size, u32 sac)
  239. {
  240. memset(tccb, 0, size);
  241. tccb->tcah.format = TCCB_FORMAT_DEFAULT;
  242. tccb->tcah.sac = sac;
  243. tccb->tcah.tcal = 12;
  244. }
  245. EXPORT_SYMBOL(tccb_init);
  246. /**
  247. * tsb_init - initialize tsb
  248. * @tsb: the tsb address
  249. *
  250. * Initialize the specified tsb by resetting all values to zero.
  251. */
  252. void tsb_init(struct tsb *tsb)
  253. {
  254. memset(tsb, 0, sizeof(*tsb));
  255. }
  256. EXPORT_SYMBOL(tsb_init);
  257. /**
  258. * tccb_add_dcw - add a dcw to the tccb
  259. * @tccb: the tccb address
  260. * @tccb_size: the maximum tccb size
  261. * @cmd: the dcw command
  262. * @flags: flags for the dcw
  263. * @cd: pointer to control data for this dcw or NULL if none is required
  264. * @cd_count: number of control data bytes for this dcw
  265. * @count: number of data bytes for this dcw
  266. *
  267. * Add a new dcw to the specified tccb by writing the dcw information specified
  268. * by @cmd, @flags, @cd, @cd_count and @count to the tca of the tccb. Return
  269. * a pointer to the newly added dcw on success or -%ENOSPC if the new dcw
  270. * would exceed the available space as defined by @tccb_size.
  271. *
  272. * Note: the tcal field of the tccb header will be updates to reflect added
  273. * content.
  274. */
  275. struct dcw *tccb_add_dcw(struct tccb *tccb, size_t tccb_size, u8 cmd, u8 flags,
  276. void *cd, u8 cd_count, u32 count)
  277. {
  278. struct dcw *dcw;
  279. int size;
  280. int tca_offset;
  281. /* Check for space. */
  282. tca_offset = tca_size(tccb);
  283. size = ALIGN(sizeof(struct dcw) + cd_count, 4);
  284. if (sizeof(struct tccb_tcah) + tca_offset + size +
  285. sizeof(struct tccb_tcat) > tccb_size)
  286. return ERR_PTR(-ENOSPC);
  287. /* Add dcw to tca. */
  288. dcw = (struct dcw *) &tccb->tca[tca_offset];
  289. memset(dcw, 0, size);
  290. dcw->cmd = cmd;
  291. dcw->flags = flags;
  292. dcw->count = count;
  293. dcw->cd_count = cd_count;
  294. if (cd)
  295. memcpy(&dcw->cd[0], cd, cd_count);
  296. tccb->tcah.tcal += size;
  297. return dcw;
  298. }
  299. EXPORT_SYMBOL(tccb_add_dcw);
  300. /**
  301. * tcw_add_tidaw - add a tidaw to a tcw
  302. * @tcw: the tcw address
  303. * @num_tidaws: the current number of tidaws
  304. * @flags: flags for the new tidaw
  305. * @addr: address value for the new tidaw
  306. * @count: count value for the new tidaw
  307. *
  308. * Add a new tidaw to the input/output data tidaw-list of the specified tcw
  309. * (depending on the value of the r-flag and w-flag) and return a pointer to
  310. * the new tidaw.
  311. *
  312. * Note: the tidaw-list is assumed to be contiguous with no ttics. The caller
  313. * must ensure that there is enough space for the new tidaw. The last-tidaw
  314. * flag for the last tidaw in the list will be set by tcw_finalize.
  315. */
  316. struct tidaw *tcw_add_tidaw(struct tcw *tcw, int num_tidaws, u8 flags,
  317. void *addr, u32 count)
  318. {
  319. struct tidaw *tidaw;
  320. /* Add tidaw to tidaw-list. */
  321. tidaw = ((struct tidaw *) tcw_get_data(tcw)) + num_tidaws;
  322. memset(tidaw, 0, sizeof(struct tidaw));
  323. tidaw->flags = flags;
  324. tidaw->count = count;
  325. tidaw->addr = (u64) ((addr_t) addr);
  326. return tidaw;
  327. }
  328. EXPORT_SYMBOL(tcw_add_tidaw);