scsi_sd.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  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 the first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #define DBG_TAG "scsi.blk"
  14. #define DBG_LVL DBG_INFO
  15. #include <rtdbg.h>
  16. #include "../block/blk_dev.h"
  17. struct scsi_sd
  18. {
  19. struct rt_blk_disk parent;
  20. struct rt_scsi_device *sdev;
  21. int sd_id;
  22. rt_bool_t use16;
  23. struct rt_device_blk_geometry geometry;
  24. };
  25. #define raw_to_scsi_sd(raw) rt_container_of(raw, struct scsi_sd, parent)
  26. static struct rt_dm_ida sd_ida = RT_DM_IDA_INIT(CUSTOM);
  27. static struct rt_dm_ida scsi_sd_ida = RT_DM_IDA_INIT(SCSI_SD);
  28. static rt_ssize_t scsi_sd_read(struct rt_blk_disk *disk, rt_off_t sector,
  29. void *buffer, rt_size_t sector_count)
  30. {
  31. rt_err_t err;
  32. struct scsi_sd *ssd = raw_to_scsi_sd(disk);
  33. struct rt_scsi_device *sdev = ssd->sdev;
  34. sector_count &= RT_UINT32_MAX;
  35. if (sector >> 32)
  36. {
  37. err = rt_scsi_read16(sdev, sector, buffer, sector_count);
  38. }
  39. else
  40. {
  41. err = rt_scsi_read10(sdev, sector, buffer, sector_count);
  42. }
  43. return !err ? sector_count : (rt_ssize_t)err;
  44. }
  45. static rt_ssize_t scsi_sd_write(struct rt_blk_disk *disk, rt_off_t sector,
  46. const void *buffer, rt_size_t sector_count)
  47. {
  48. rt_err_t err;
  49. struct scsi_sd *ssd = raw_to_scsi_sd(disk);
  50. struct rt_scsi_device *sdev = ssd->sdev;
  51. sector_count &= RT_UINT32_MAX;
  52. if (sector >> 32)
  53. {
  54. err = rt_scsi_write16(sdev, sector, buffer, sector_count);
  55. }
  56. else
  57. {
  58. err = rt_scsi_write10(sdev, sector, buffer, sector_count);
  59. }
  60. return !err ? sector_count : (rt_ssize_t)err;
  61. }
  62. static rt_err_t scsi_sd_getgeome(struct rt_blk_disk *disk,
  63. struct rt_device_blk_geometry *geometry)
  64. {
  65. struct scsi_sd *ssd = raw_to_scsi_sd(disk);
  66. rt_memcpy(geometry, &ssd->geometry, sizeof(ssd->geometry));
  67. return RT_EOK;
  68. }
  69. static rt_err_t scsi_sd_sync(struct rt_blk_disk *disk)
  70. {
  71. rt_err_t err;
  72. rt_size_t lba_count;
  73. struct scsi_sd *ssd = raw_to_scsi_sd(disk);
  74. struct rt_scsi_device *sdev = ssd->sdev;
  75. lba_count = ssd->geometry.sector_count;
  76. if (ssd->use16)
  77. {
  78. err = rt_scsi_synchronize_cache16(sdev, 0, lba_count);
  79. }
  80. else
  81. {
  82. err = rt_scsi_synchronize_cache10(sdev, 0, lba_count);
  83. }
  84. return err;
  85. }
  86. static rt_err_t scsi_sd_erase(struct rt_blk_disk *disk)
  87. {
  88. rt_err_t err;
  89. rt_size_t lba_count;
  90. struct scsi_sd *ssd = raw_to_scsi_sd(disk);
  91. struct rt_scsi_device *sdev = ssd->sdev;
  92. lba_count = ssd->geometry.sector_count;
  93. if (ssd->use16)
  94. {
  95. err = rt_scsi_write_same16(sdev, 0, lba_count);
  96. }
  97. else
  98. {
  99. err = rt_scsi_write_same10(sdev, 0, lba_count);
  100. }
  101. return err;
  102. }
  103. static rt_err_t scsi_sd_autorefresh(struct rt_blk_disk *disk, rt_bool_t is_auto)
  104. {
  105. rt_err_t err;
  106. int sp;
  107. rt_size_t size;
  108. rt_uint8_t buffer[64];
  109. rt_uint8_t *buffer_data;
  110. rt_bool_t use6 = RT_TRUE;
  111. struct scsi_sd *ssd = raw_to_scsi_sd(disk);
  112. struct rt_scsi_device *sdev = ssd->sdev;
  113. struct rt_scsi_mode_select_data data;
  114. err = rt_scsi_mode_sense6(sdev, 0x08, 8, 0, buffer, sizeof(buffer), &data);
  115. if (err && err != -RT_ENOMEM)
  116. {
  117. use6 = RT_FALSE;
  118. err = rt_scsi_mode_sense10(sdev, 0x08, 8, 0, buffer, sizeof(buffer), &data);
  119. }
  120. if (err)
  121. {
  122. return err;
  123. }
  124. size = rt_min_t(rt_size_t, sizeof(buffer),
  125. data.length - data.header_length - data.block_descriptor_length);
  126. buffer_data = buffer + data.header_length + data.block_descriptor_length;
  127. buffer_data[2] &= ~0x05;
  128. buffer_data[2] |= (!!is_auto) << 2 | (!!is_auto);
  129. sp = buffer_data[0] & 0x80 ? 1 : 0;
  130. buffer_data[0] &= ~0x80;
  131. data.device_specific = 0;
  132. if (use6)
  133. {
  134. err = rt_scsi_mode_select6(sdev, 1, sp, buffer_data, size, &data);
  135. }
  136. else
  137. {
  138. err = rt_scsi_mode_select10(sdev, 1, sp, buffer_data, size, &data);
  139. }
  140. return err;
  141. }
  142. static const struct rt_blk_disk_ops scsi_sd_ops =
  143. {
  144. .read = scsi_sd_read,
  145. .write = scsi_sd_write,
  146. .getgeome = scsi_sd_getgeome,
  147. .sync = scsi_sd_sync,
  148. .erase = scsi_sd_erase,
  149. .autorefresh = scsi_sd_autorefresh,
  150. };
  151. rt_err_t scsi_sd_probe(struct rt_scsi_device *sdev)
  152. {
  153. rt_err_t err;
  154. union
  155. {
  156. struct rt_scsi_read_capacity10_data capacity10;
  157. struct rt_scsi_read_capacity16_data capacity16;
  158. } data;
  159. struct scsi_sd *ssd = rt_calloc(1, sizeof(*ssd));
  160. if (!ssd)
  161. {
  162. return -RT_ENOMEM;
  163. }
  164. if ((ssd->sd_id = rt_dm_ida_alloc(&sd_ida)) < 0)
  165. {
  166. return -RT_EFULL;
  167. }
  168. sdev->priv = ssd;
  169. ssd->sdev = sdev;
  170. ssd->parent.ida = &scsi_sd_ida;
  171. ssd->parent.parallel_io = RT_FALSE;
  172. ssd->parent.ops = &scsi_sd_ops;
  173. ssd->parent.max_partitions = RT_BLK_PARTITION_MAX;
  174. if ((err = rt_scsi_read_capacity10(sdev, &data.capacity10)))
  175. {
  176. goto _fail;
  177. }
  178. if (data.capacity10.last_block == 0xffffffff)
  179. {
  180. if ((err = rt_scsi_read_capacity16(sdev, &data.capacity16)))
  181. {
  182. goto _fail;
  183. }
  184. ssd->use16 = RT_TRUE;
  185. }
  186. ssd->geometry.bytes_per_sector = sdev->block_size;
  187. ssd->geometry.block_size = sdev->block_size;
  188. ssd->geometry.sector_count = sdev->last_block + 1;
  189. rt_dm_dev_set_name(&ssd->parent.parent, "sd%c%c", letter_name(ssd->sd_id));
  190. if ((err = rt_hw_blk_disk_register(&ssd->parent)))
  191. {
  192. goto _fail;
  193. }
  194. return RT_EOK;
  195. _fail:
  196. rt_dm_ida_free(&sd_ida, ssd->sd_id);
  197. rt_free(ssd);
  198. return err;
  199. }
  200. rt_err_t scsi_sd_remove(struct rt_scsi_device *sdev)
  201. {
  202. struct scsi_sd *ssd = sdev->priv;
  203. rt_dm_ida_free(&sd_ida, ssd->sd_id);
  204. return rt_hw_blk_disk_unregister(&ssd->parent);
  205. }