Commit 7981ea00 authored by Daniel DeGrasse's avatar Daniel DeGrasse Committed by Fabio Baltieri
Browse files

fs: fat_fs: make IOCTL call to de-initialize disk in fatfs_unmount()



Make call to de-initialize disk in fatfs_unmount(). This will permit the
disk to be reinitialized when it is mounted with fatfs_mount().

Signed-off-by: default avatarDaniel DeGrasse <daniel.degrasse@nxp.com>
parent 93ebf1c4
Loading
Loading
Loading
Loading
+25 −6
Original line number Diff line number Diff line
/*
 * Copyright (c) 2018-2021 Zephyr contributors
 * Copyright (c) 2022 Nordic Semiconductor ASA
 * Copyright 2024 NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */
@@ -12,6 +13,7 @@
 */
#include <ff.h>
#include <diskio.h>	/* FatFs lower layer API */
#include <zfs_diskio.h> /* Zephyr specific FatFS API */
#include <zephyr/storage/disk_access.h>

static const char * const pdrv_str[] = {FF_VOLUME_STRS};
@@ -31,13 +33,9 @@ DSTATUS disk_status(BYTE pdrv)
/* Initialize a Drive */
DSTATUS disk_initialize(BYTE pdrv)
{
	__ASSERT(pdrv < ARRAY_SIZE(pdrv_str), "pdrv out-of-range\n");
	uint8_t param = DISK_IOCTL_POWER_ON;

	if (disk_access_init(pdrv_str[pdrv]) != 0) {
		return STA_NOINIT;
	} else {
		return RES_OK;
	}
	return disk_ioctl(pdrv, CTRL_POWER, &param);
}

/* Read Sector(s) */
@@ -109,6 +107,27 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff)
		}
		break;

	/* Optional IOCTL command used by Zephyr fs_unmount implementation,
	 * not called by FATFS
	 */
	case CTRL_POWER:
		if (((*(uint8_t *)buff)) == DISK_IOCTL_POWER_OFF) {
			/* Power disk off */
			if (disk_access_ioctl(pdrv_str[pdrv],
					      DISK_IOCTL_CTRL_DEINIT,
					      NULL) != 0) {
				ret = RES_ERROR;
			}
		} else {
			/* Power disk on */
			if (disk_access_ioctl(pdrv_str[pdrv],
					      DISK_IOCTL_CTRL_INIT,
					      NULL) != 0) {
				ret = STA_NOINIT;
			}
		}
		break;

	default:
		ret = RES_PARERR;
		break;
+22 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef ZEPHYR_MODULES_FATFS_ZFS_DISKIO_H_
#define ZEPHYR_MODULES_FATFS_ZFS_DISKIO_H_
/*
 * Header file for Zephyr specific portions of the FatFS disk interface.
 * These APIs are internal to Zephyr's FatFS VFS implementation
 */

/*
 * Values that can be passed to buffer pointer used by disk_ioctl() when
 * sending CTRL_POWER IOCTL
 */
#define DISK_IOCTL_POWER_OFF 0x0
#define DISK_IOCTL_POWER_ON 0x1


#endif /* ZEPHYR_MODULES_FATFS_ZFS_DISKIO_H_ */
+36 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2016 Intel Corporation.
 * Copyright 2024 NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */
@@ -14,6 +15,10 @@
#include <zephyr/fs/fs_sys.h>
#include <zephyr/sys/__assert.h>
#include <ff.h>
#include <diskio.h>
#include <zfs_diskio.h> /* Zephyr specific FatFS API */
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(fs, CONFIG_FS_LOG_LEVEL);

#define FATFS_MAX_FILE_NAME 12 /* Uses 8.3 SFN */

@@ -64,6 +69,23 @@ static int translate_error(int error)
	return -EIO;
}

static int translate_disk_error(int error)
{
	switch (error) {
	case RES_OK:
		return 0;
	case RES_WRPRT:
		return -EPERM;
	case RES_PARERR:
		return -EINVAL;
	case RES_NOTRDY:
	case RES_ERROR:
		return -EIO;
	}

	return -EIO;
}

/* Converts a zephyr path like /SD:/foo into a path digestible by FATFS by stripping the
 * leading slash, i.e. SD:/foo.
 */
@@ -463,12 +485,25 @@ static int fatfs_mount(struct fs_mount_t *mountp)
static int fatfs_unmount(struct fs_mount_t *mountp)
{
	FRESULT res;
	DRESULT disk_res;
	uint8_t param = DISK_IOCTL_POWER_OFF;

	res = f_mount(NULL, translate_path(mountp->mnt_point), 0);

	if (res != FR_OK) {
		LOG_ERR("Unmount failed (%d)", res);
		return translate_error(res);
	}

	/* Make direct disk IOCTL call to deinit disk */
	disk_res = disk_ioctl(((FATFS *)mountp->fs_data)->pdrv, CTRL_POWER, &param);
	if (disk_res != RES_OK) {
		LOG_ERR("Could not power off disk (%d)", disk_res);
		return translate_disk_error(disk_res);
	}

	return 0;
}

#if defined(CONFIG_FILE_SYSTEM_MKFS) && defined(CONFIG_FS_FATFS_MKFS)

static MKFS_PARM def_cfg = {