1 /*
2 * Copyright (c) 2018-2021 Zephyr contributors
3 * Copyright (c) 2022 Nordic Semiconductor ASA
4 * Copyright 2024 NXP
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8 /* The file is based on template file by (C)ChaN, 2019, as
9 * available from FAT FS module source:
10 * https://github.com/zephyrproject-rtos/fatfs/blob/master/diskio.c
11 * and has been previously avaialble from directory for that module
12 * under name zfs_diskio.c.
13 */
14 #include <ff.h>
15 #include <diskio.h> /* FatFs lower layer API */
16 #include <zfs_diskio.h> /* Zephyr specific FatFS API */
17 #include <zephyr/storage/disk_access.h>
18
19 static const char * const pdrv_str[] = {FF_VOLUME_STRS};
20
21 /* Get Drive Status */
disk_status(BYTE pdrv)22 DSTATUS disk_status(BYTE pdrv)
23 {
24 __ASSERT(pdrv < ARRAY_SIZE(pdrv_str), "pdrv out-of-range\n");
25
26 if (disk_access_status(pdrv_str[pdrv]) != 0) {
27 return STA_NOINIT;
28 } else {
29 return RES_OK;
30 }
31 }
32
33 /* Initialize a Drive */
disk_initialize(BYTE pdrv)34 DSTATUS disk_initialize(BYTE pdrv)
35 {
36 uint8_t param = DISK_IOCTL_POWER_ON;
37
38 return disk_ioctl(pdrv, CTRL_POWER, ¶m);
39 }
40
41 /* Read Sector(s) */
disk_read(BYTE pdrv,BYTE * buff,LBA_t sector,UINT count)42 DRESULT disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count)
43 {
44 __ASSERT(pdrv < ARRAY_SIZE(pdrv_str), "pdrv out-of-range\n");
45
46 if (disk_access_read(pdrv_str[pdrv], buff, sector, count) != 0) {
47 return RES_ERROR;
48 } else {
49 return RES_OK;
50 }
51
52 }
53
54 /* Write Sector(s) */
disk_write(BYTE pdrv,const BYTE * buff,LBA_t sector,UINT count)55 DRESULT disk_write(BYTE pdrv, const BYTE *buff, LBA_t sector, UINT count)
56 {
57 __ASSERT(pdrv < ARRAY_SIZE(pdrv_str), "pdrv out-of-range\n");
58
59 if (disk_access_write(pdrv_str[pdrv], buff, sector, count) != 0) {
60 return RES_ERROR;
61 } else {
62 return RES_OK;
63 }
64 }
65
66 /* Miscellaneous Functions */
disk_ioctl(BYTE pdrv,BYTE cmd,void * buff)67 DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
68 {
69 int ret = RES_OK;
70 uint32_t sector_size = 0;
71
72 __ASSERT(pdrv < ARRAY_SIZE(pdrv_str), "pdrv out-of-range\n");
73
74 switch (cmd) {
75 case CTRL_SYNC:
76 if (disk_access_ioctl(pdrv_str[pdrv],
77 DISK_IOCTL_CTRL_SYNC, buff) != 0) {
78 ret = RES_ERROR;
79 }
80 break;
81
82 case GET_SECTOR_COUNT:
83 if (disk_access_ioctl(pdrv_str[pdrv],
84 DISK_IOCTL_GET_SECTOR_COUNT, buff) != 0) {
85 ret = RES_ERROR;
86 }
87 break;
88
89 case GET_SECTOR_SIZE:
90 /* Zephyr's DISK_IOCTL_GET_SECTOR_SIZE returns sector size as a
91 * 32-bit number while FatFS's GET_SECTOR_SIZE is supposed to
92 * return a 16-bit number.
93 */
94 if ((disk_access_ioctl(pdrv_str[pdrv],
95 DISK_IOCTL_GET_SECTOR_SIZE, §or_size) == 0) &&
96 (sector_size == (uint16_t)sector_size)) {
97 *(uint16_t *)buff = (uint16_t)sector_size;
98 } else {
99 ret = RES_ERROR;
100 }
101 break;
102
103 case GET_BLOCK_SIZE:
104 if (disk_access_ioctl(pdrv_str[pdrv],
105 DISK_IOCTL_GET_ERASE_BLOCK_SZ, buff) != 0) {
106 ret = RES_ERROR;
107 }
108 break;
109
110 /* Optional IOCTL command used by Zephyr fs_unmount implementation,
111 * not called by FATFS
112 */
113 case CTRL_POWER:
114 if (((*(uint8_t *)buff)) == DISK_IOCTL_POWER_OFF) {
115 /* Power disk off */
116 if (disk_access_ioctl(pdrv_str[pdrv],
117 DISK_IOCTL_CTRL_DEINIT,
118 NULL) != 0) {
119 ret = RES_ERROR;
120 }
121 } else {
122 /* Power disk on */
123 if (disk_access_ioctl(pdrv_str[pdrv],
124 DISK_IOCTL_CTRL_INIT,
125 NULL) != 0) {
126 ret = STA_NOINIT;
127 }
128 }
129 break;
130
131 default:
132 ret = RES_PARERR;
133 break;
134 }
135 return ret;
136 }
137