vfs_fat_diskio.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * Original template for this file comes from:
  5. * Low level disk I/O module skeleton for FatFs, (C)ChaN, 2013
  6. *
  7. * The MIT License (MIT)
  8. *
  9. * Copyright (c) 2013, 2014 Damien P. George
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a copy
  12. * of this software and associated documentation files (the "Software"), to deal
  13. * in the Software without restriction, including without limitation the rights
  14. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  15. * copies of the Software, and to permit persons to whom the Software is
  16. * furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be included in
  19. * all copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  22. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  24. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  26. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  27. * THE SOFTWARE.
  28. */
  29. #include "py/mpconfig.h"
  30. #if MICROPY_VFS && MICROPY_VFS_FAT
  31. #include <stdint.h>
  32. #include <stdio.h>
  33. #include "py/mphal.h"
  34. #include "py/runtime.h"
  35. #include "py/binary.h"
  36. #include "py/objarray.h"
  37. #include "py/mperrno.h"
  38. #include "lib/oofatfs/ff.h"
  39. #include "lib/oofatfs/diskio.h"
  40. #include "extmod/vfs_fat.h"
  41. typedef void *bdev_t;
  42. STATIC fs_user_mount_t *disk_get_device(void *bdev) {
  43. return (fs_user_mount_t*)bdev;
  44. }
  45. /*-----------------------------------------------------------------------*/
  46. /* Read Sector(s) */
  47. /*-----------------------------------------------------------------------*/
  48. DRESULT disk_read (
  49. bdev_t pdrv, /* Physical drive nmuber (0..) */
  50. BYTE *buff, /* Data buffer to store read data */
  51. DWORD sector, /* Sector address (LBA) */
  52. UINT count /* Number of sectors to read (1..128) */
  53. )
  54. {
  55. fs_user_mount_t *vfs = disk_get_device(pdrv);
  56. if (vfs == NULL) {
  57. return RES_PARERR;
  58. }
  59. int ret = mp_vfs_blockdev_read(&vfs->blockdev, sector, count, buff);
  60. return ret == 0 ? RES_OK : RES_ERROR;
  61. }
  62. /*-----------------------------------------------------------------------*/
  63. /* Write Sector(s) */
  64. /*-----------------------------------------------------------------------*/
  65. DRESULT disk_write (
  66. bdev_t pdrv, /* Physical drive nmuber (0..) */
  67. const BYTE *buff, /* Data to be written */
  68. DWORD sector, /* Sector address (LBA) */
  69. UINT count /* Number of sectors to write (1..128) */
  70. )
  71. {
  72. fs_user_mount_t *vfs = disk_get_device(pdrv);
  73. if (vfs == NULL) {
  74. return RES_PARERR;
  75. }
  76. int ret = mp_vfs_blockdev_write(&vfs->blockdev, sector, count, buff);
  77. if (ret == -MP_EROFS) {
  78. // read-only block device
  79. return RES_WRPRT;
  80. }
  81. return ret == 0 ? RES_OK : RES_ERROR;
  82. }
  83. /*-----------------------------------------------------------------------*/
  84. /* Miscellaneous Functions */
  85. /*-----------------------------------------------------------------------*/
  86. DRESULT disk_ioctl (
  87. bdev_t pdrv, /* Physical drive nmuber (0..) */
  88. BYTE cmd, /* Control code */
  89. void *buff /* Buffer to send/receive control data */
  90. )
  91. {
  92. fs_user_mount_t *vfs = disk_get_device(pdrv);
  93. if (vfs == NULL) {
  94. return RES_PARERR;
  95. }
  96. // First part: call the relevant method of the underlying block device
  97. static const uint8_t op_map[8] = {
  98. [CTRL_SYNC] = MP_BLOCKDEV_IOCTL_SYNC,
  99. [GET_SECTOR_COUNT] = MP_BLOCKDEV_IOCTL_BLOCK_COUNT,
  100. [GET_SECTOR_SIZE] = MP_BLOCKDEV_IOCTL_BLOCK_SIZE,
  101. [IOCTL_INIT] = MP_BLOCKDEV_IOCTL_INIT,
  102. };
  103. uint8_t bp_op = op_map[cmd & 7];
  104. mp_obj_t ret = mp_const_none;
  105. if (bp_op != 0) {
  106. ret = mp_vfs_blockdev_ioctl(&vfs->blockdev, bp_op, 0);
  107. }
  108. // Second part: convert the result for return
  109. switch (cmd) {
  110. case CTRL_SYNC:
  111. return RES_OK;
  112. case GET_SECTOR_COUNT: {
  113. *((DWORD*)buff) = mp_obj_get_int(ret);
  114. return RES_OK;
  115. }
  116. case GET_SECTOR_SIZE: {
  117. if (ret == mp_const_none) {
  118. // Default sector size
  119. *((WORD*)buff) = 512;
  120. } else {
  121. *((WORD*)buff) = mp_obj_get_int(ret);
  122. }
  123. // need to store ssize because we use it in disk_read/disk_write
  124. vfs->blockdev.block_size = *((WORD*)buff);
  125. return RES_OK;
  126. }
  127. case GET_BLOCK_SIZE:
  128. *((DWORD*)buff) = 1; // erase block size in units of sector size
  129. return RES_OK;
  130. case IOCTL_INIT:
  131. case IOCTL_STATUS: {
  132. DSTATUS stat;
  133. if (ret != mp_const_none && MP_OBJ_SMALL_INT_VALUE(ret) != 0) {
  134. // error initialising
  135. stat = STA_NOINIT;
  136. } else if (vfs->blockdev.writeblocks[0] == MP_OBJ_NULL) {
  137. stat = STA_PROTECT;
  138. } else {
  139. stat = 0;
  140. }
  141. *((DSTATUS*)buff) = stat;
  142. return RES_OK;
  143. }
  144. default:
  145. return RES_PARERR;
  146. }
  147. }
  148. #endif // MICROPY_VFS && MICROPY_VFS_FAT