blk_dev.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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-02-25 GuEe-GUI first version
  9. */
  10. #include "blk_dev.h"
  11. #include "blk_dfs.h"
  12. #define DBG_TAG "blk.dm"
  13. #define DBG_LVL DBG_INFO
  14. #include <rtdbg.h>
  15. #ifdef RT_USING_DFS
  16. #include <dfs_fs.h>
  17. #endif
  18. static rt_err_t blk_dev_open(rt_device_t dev, rt_uint16_t oflag)
  19. {
  20. struct rt_blk_device *blk = to_blk(dev);
  21. return rt_device_open(&blk->disk->parent, oflag);
  22. }
  23. static rt_err_t blk_dev_close(rt_device_t dev)
  24. {
  25. struct rt_blk_device *blk = to_blk(dev);
  26. return rt_device_close(&blk->disk->parent);
  27. }
  28. static rt_ssize_t blk_dev_read(rt_device_t dev, rt_off_t sector,
  29. void *buffer, rt_size_t sector_count)
  30. {
  31. struct rt_blk_device *blk = to_blk(dev);
  32. if (sector <= blk->sector_start + blk->sector_count &&
  33. sector_count <= blk->sector_count)
  34. {
  35. return rt_device_read(&blk->disk->parent,
  36. blk->sector_start + sector, buffer, sector_count);
  37. }
  38. return -RT_EINVAL;
  39. }
  40. static rt_ssize_t blk_dev_write(rt_device_t dev, rt_off_t sector,
  41. const void *buffer, rt_size_t sector_count)
  42. {
  43. struct rt_blk_device *blk = to_blk(dev);
  44. if (sector <= blk->sector_start + blk->sector_count &&
  45. sector_count <= blk->sector_count)
  46. {
  47. return rt_device_write(&blk->disk->parent,
  48. blk->sector_start + sector, buffer, sector_count);
  49. }
  50. return -RT_EINVAL;
  51. }
  52. static rt_err_t blk_dev_control(rt_device_t dev, int cmd, void *args)
  53. {
  54. rt_err_t err = -RT_EINVAL;
  55. struct rt_blk_device *blk = to_blk(dev);
  56. struct rt_blk_disk *disk = blk->disk;
  57. struct rt_device_blk_geometry disk_geometry, *geometry;
  58. switch (cmd)
  59. {
  60. case RT_DEVICE_CTRL_BLK_GETGEOME:
  61. if ((geometry = args))
  62. {
  63. if (!(err = disk->ops->getgeome(disk, &disk_geometry)))
  64. {
  65. geometry->bytes_per_sector = disk_geometry.bytes_per_sector;
  66. geometry->block_size = disk_geometry.block_size;
  67. geometry->sector_count = blk->sector_count;
  68. }
  69. }
  70. else
  71. {
  72. err = -RT_EINVAL;
  73. }
  74. break;
  75. case RT_DEVICE_CTRL_BLK_SYNC:
  76. rt_device_control(&disk->parent, cmd, args);
  77. break;
  78. case RT_DEVICE_CTRL_BLK_ERASE:
  79. case RT_DEVICE_CTRL_BLK_AUTOREFRESH:
  80. if (disk->partitions <= 1)
  81. {
  82. rt_device_control(&disk->parent, cmd, args);
  83. }
  84. else
  85. {
  86. err = -RT_EIO;
  87. }
  88. break;
  89. case RT_DEVICE_CTRL_BLK_PARTITION:
  90. if (args)
  91. {
  92. rt_memcpy(args, &blk->partition, sizeof(blk->partition));
  93. }
  94. else
  95. {
  96. err = -RT_EINVAL;
  97. }
  98. break;
  99. case RT_DEVICE_CTRL_BLK_SSIZEGET:
  100. device_get_blk_ssize(dev, args);
  101. err = RT_EOK;
  102. break;
  103. case RT_DEVICE_CTRL_ALL_BLK_SSIZEGET:
  104. device_get_all_blk_ssize(dev, args);
  105. err = RT_EOK;
  106. break;
  107. default:
  108. if (disk->ops->control)
  109. {
  110. err = disk->ops->control(disk, blk, cmd, args);
  111. }
  112. break;
  113. }
  114. return err;
  115. }
  116. #ifdef RT_USING_DEVICE_OPS
  117. const static struct rt_device_ops blk_dev_ops =
  118. {
  119. .open = blk_dev_open,
  120. .close = blk_dev_close,
  121. .read = blk_dev_read,
  122. .write = blk_dev_write,
  123. .control = blk_dev_control,
  124. };
  125. #endif
  126. rt_err_t blk_dev_initialize(struct rt_blk_device *blk)
  127. {
  128. struct rt_device *dev;
  129. if (!blk)
  130. {
  131. return -RT_EINVAL;
  132. }
  133. dev = &blk->parent;
  134. dev->type = RT_Device_Class_Block;
  135. #ifdef RT_USING_DEVICE_OPS
  136. dev->ops = &blk_dev_ops;
  137. #else
  138. dev->open = blk_dev_open;
  139. dev->close = blk_dev_close;
  140. dev->read = blk_dev_read;
  141. dev->write = blk_dev_write;
  142. dev->control = blk_dev_control;
  143. #endif
  144. return RT_EOK;
  145. }
  146. rt_err_t disk_add_blk_dev(struct rt_blk_disk *disk, struct rt_blk_device *blk)
  147. {
  148. rt_err_t err;
  149. #ifdef RT_USING_DM
  150. int device_id;
  151. #endif
  152. const char *disk_name, *name_fmt;
  153. if (!disk || !blk)
  154. {
  155. return -RT_EINVAL;
  156. }
  157. #ifdef RT_USING_DM
  158. if ((device_id = rt_dm_ida_alloc(disk->ida)) < 0)
  159. {
  160. return -RT_EFULL;
  161. }
  162. #endif
  163. blk->disk = disk;
  164. rt_list_init(&blk->list);
  165. disk_name = to_disk_name(disk);
  166. /* End is [a-zA-Z] or [0-9] */
  167. if (disk_name[rt_strlen(disk_name) - 1] < 'a')
  168. {
  169. name_fmt = "%sp%d";
  170. }
  171. else
  172. {
  173. name_fmt = "%s%d";
  174. }
  175. #ifdef RT_USING_DM
  176. rt_dm_dev_set_name(&blk->parent, name_fmt, disk_name, blk->partno);
  177. blk->parent.master_id = disk->ida->master_id;
  178. blk->parent.device_id = device_id;
  179. #else
  180. rt_snprintf(blk->parent.parent.name, RT_NAME_MAX, name_fmt, disk_name, blk->partno);
  181. #endif
  182. device_set_blk_fops(&blk->parent);
  183. err = rt_device_register(&blk->parent, to_blk_name(blk),
  184. disk->parent.flag & RT_DEVICE_FLAG_RDWR);
  185. if (err)
  186. {
  187. #ifdef RT_USING_DM
  188. rt_dm_ida_free(disk->ida, device_id);
  189. #endif
  190. return err;
  191. }
  192. spin_lock(&disk->lock);
  193. rt_list_insert_before(&disk->part_nodes, &blk->list);
  194. spin_unlock(&disk->lock);
  195. return RT_EOK;
  196. }
  197. rt_err_t disk_remove_blk_dev(struct rt_blk_device *blk, rt_bool_t lockless)
  198. {
  199. struct rt_blk_disk *disk;
  200. if (!blk)
  201. {
  202. return -RT_EINVAL;
  203. }
  204. disk = blk->disk;
  205. if (!disk)
  206. {
  207. return -RT_EINVAL;
  208. }
  209. else
  210. {
  211. #ifdef RT_USING_DFS
  212. const char *mountpath;
  213. if ((mountpath = dfs_filesystem_get_mounted_path(&blk->parent)))
  214. {
  215. dfs_unmount(mountpath);
  216. LOG_D("%s: Unmount file system on %s",
  217. to_blk_name(blk), mountpath);
  218. }
  219. #endif
  220. }
  221. #ifdef RT_USING_DM
  222. rt_dm_ida_free(disk->ida, blk->parent.device_id);
  223. #endif
  224. rt_device_unregister(&blk->parent);
  225. if (!lockless)
  226. {
  227. spin_lock(&disk->lock);
  228. }
  229. rt_list_remove(&blk->list);
  230. if (!lockless)
  231. {
  232. spin_unlock(&disk->lock);
  233. }
  234. --disk->partitions;
  235. return RT_EOK;
  236. }
  237. rt_uint32_t blk_request_ioprio(void)
  238. {
  239. struct rt_thread *task = rt_thread_self();
  240. return task ? RT_SCHED_PRIV(task).current_priority : 0;
  241. }