blk_dfs.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-08-08 GuEe-GUI first version
  9. */
  10. #include "blk_dfs.h"
  11. #include <dfs_file.h>
  12. #include <drivers/classes/block.h>
  13. #if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_DFS_V2)
  14. struct blk_fops_data
  15. {
  16. struct rt_device_blk_geometry geometry;
  17. };
  18. static int blk_fops_open(struct dfs_file *file)
  19. {
  20. struct rt_device *dev = file->vnode->data;
  21. struct blk_fops_data *data = rt_malloc(sizeof(*data));
  22. if (!data)
  23. {
  24. return (int)-RT_ENOMEM;
  25. }
  26. dev->user_data = data;
  27. rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &data->geometry);
  28. rt_device_control(dev, RT_DEVICE_CTRL_ALL_BLK_SSIZEGET, &file->vnode->size);
  29. return 0;
  30. }
  31. static int blk_fops_close(struct dfs_file *file)
  32. {
  33. struct rt_device *dev = file->vnode->data;
  34. rt_free(dev->user_data);
  35. dev->user_data = RT_NULL;
  36. return 0;
  37. }
  38. static int blk_fops_ioctl(struct dfs_file *file, int cmd, void *arg)
  39. {
  40. struct rt_device *dev = file->vnode->data;
  41. return (int)rt_device_control(dev, cmd, arg);
  42. }
  43. static ssize_t blk_fops_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
  44. {
  45. void *rbuf;
  46. rt_ssize_t res = 0;
  47. int bytes_per_sector, blk_pos, first_offs, rsize = 0;
  48. struct rt_device *dev = file->vnode->data;
  49. struct blk_fops_data *data = dev->user_data;
  50. bytes_per_sector = data->geometry.bytes_per_sector;
  51. blk_pos = *pos / bytes_per_sector;
  52. first_offs = *pos % bytes_per_sector;
  53. if ((rbuf = rt_malloc(bytes_per_sector)))
  54. {
  55. /*
  56. ** #1: read first unalign block size.
  57. */
  58. res = rt_device_read(dev, blk_pos, rbuf, 1);
  59. if (res == 1)
  60. {
  61. if (count > bytes_per_sector - first_offs)
  62. {
  63. rsize = bytes_per_sector - first_offs;
  64. }
  65. else
  66. {
  67. rsize = count;
  68. }
  69. rt_memcpy(buf, rbuf + first_offs, rsize);
  70. ++blk_pos;
  71. /*
  72. ** #2: read continuous block size.
  73. */
  74. while (rsize < count)
  75. {
  76. res = rt_device_read(dev, blk_pos++, rbuf, 1);
  77. if (res != 1)
  78. {
  79. break;
  80. }
  81. if (count - rsize >= bytes_per_sector)
  82. {
  83. rt_memcpy(buf + rsize, rbuf, bytes_per_sector);
  84. rsize += bytes_per_sector;
  85. }
  86. else
  87. {
  88. rt_memcpy(buf + rsize, rbuf, count - rsize);
  89. rsize = count;
  90. }
  91. }
  92. *pos += rsize;
  93. }
  94. rt_free(rbuf);
  95. }
  96. return rsize;
  97. }
  98. static ssize_t blk_fops_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
  99. {
  100. void *rbuf;
  101. rt_ssize_t res = 0;
  102. int bytes_per_sector, blk_pos, first_offs, wsize = 0;
  103. struct rt_device *dev = file->vnode->data;
  104. struct blk_fops_data *data = dev->user_data;
  105. bytes_per_sector = data->geometry.bytes_per_sector;
  106. blk_pos = *pos / bytes_per_sector;
  107. first_offs = *pos % bytes_per_sector;
  108. /*
  109. ** #1: write first unalign block size.
  110. */
  111. if (first_offs != 0)
  112. {
  113. if (count > bytes_per_sector - first_offs)
  114. {
  115. wsize = bytes_per_sector - first_offs;
  116. }
  117. else
  118. {
  119. wsize = count;
  120. }
  121. if ((rbuf = rt_malloc(bytes_per_sector)))
  122. {
  123. res = rt_device_read(dev, blk_pos, rbuf, 1);
  124. if (res == 1)
  125. {
  126. rt_memcpy(rbuf + first_offs, buf, wsize);
  127. res = rt_device_write(dev, blk_pos, (const void *)rbuf, 1);
  128. if (res == 1)
  129. {
  130. blk_pos += 1;
  131. rt_free(rbuf);
  132. goto _goon;
  133. }
  134. }
  135. rt_free(rbuf);
  136. }
  137. return 0;
  138. }
  139. _goon:
  140. /*
  141. ** #2: write continuous block size.
  142. */
  143. if ((count - wsize) / bytes_per_sector != 0)
  144. {
  145. res = rt_device_write(dev, blk_pos, buf + wsize, (count - wsize) / bytes_per_sector);
  146. wsize += res * bytes_per_sector;
  147. blk_pos += res;
  148. if (res != (count - wsize) / bytes_per_sector)
  149. {
  150. *pos += wsize;
  151. return wsize;
  152. }
  153. }
  154. /*
  155. ** # 3: write last unalign block size.
  156. */
  157. if ((count - wsize) != 0)
  158. {
  159. if ((rbuf = rt_malloc(bytes_per_sector)))
  160. {
  161. res = rt_device_read(dev, blk_pos, rbuf, 1);
  162. if (res == 1)
  163. {
  164. rt_memcpy(rbuf, buf + wsize, count - wsize);
  165. res = rt_device_write(dev, blk_pos, (const void *)rbuf, 1);
  166. if (res == 1)
  167. {
  168. wsize += count - wsize;
  169. }
  170. }
  171. rt_free(rbuf);
  172. }
  173. }
  174. *pos += wsize;
  175. return wsize;
  176. }
  177. static int blk_fops_flush(struct dfs_file *file)
  178. {
  179. struct rt_device *dev = file->vnode->data;
  180. return (int)rt_device_control(dev, RT_DEVICE_CTRL_BLK_SYNC, RT_NULL);
  181. }
  182. static int blk_fops_poll(struct dfs_file *file, struct rt_pollreq *req)
  183. {
  184. int mask = 0;
  185. return mask;
  186. }
  187. const static struct dfs_file_ops blk_fops =
  188. {
  189. .open = blk_fops_open,
  190. .close = blk_fops_close,
  191. .ioctl = blk_fops_ioctl,
  192. .read = blk_fops_read,
  193. .write = blk_fops_write,
  194. .flush = blk_fops_flush,
  195. .lseek = generic_dfs_lseek,
  196. .poll = blk_fops_poll
  197. };
  198. void device_set_blk_fops(struct rt_device *dev)
  199. {
  200. dev->fops = &blk_fops;
  201. }
  202. #else
  203. void device_set_blk_fops(struct rt_device *dev)
  204. {
  205. }
  206. #endif /* RT_USING_POSIX_DEVIO && RT_USING_DFS_V2 */
  207. void device_get_blk_ssize(struct rt_device *dev, void *args)
  208. {
  209. rt_uint32_t bytes_per_sector;
  210. struct rt_device_blk_geometry geometry;
  211. rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
  212. bytes_per_sector = geometry.bytes_per_sector;
  213. RT_ASSERT(sizeof(bytes_per_sector) == sizeof(geometry.bytes_per_sector));
  214. rt_memcpy(args, &bytes_per_sector, sizeof(bytes_per_sector));
  215. }
  216. void device_get_all_blk_ssize(struct rt_device *dev, void *args)
  217. {
  218. rt_uint64_t count_mul_per;
  219. struct rt_device_blk_geometry geometry;
  220. rt_device_control(dev, RT_DEVICE_CTRL_BLK_GETGEOME, &geometry);
  221. count_mul_per = geometry.bytes_per_sector * geometry.sector_count;
  222. rt_memcpy(args, &count_mul_per, sizeof(count_mul_per));
  223. }