diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt index d957856..fdbaeab 100644 --- a/linux/CMakeLists.txt +++ b/linux/CMakeLists.txt @@ -5,7 +5,7 @@ if (NOT "${CMAKE_SYSTEM}" MATCHES "Linux") endif () set(PLATFORM_SOURCES list_devices.c linux.h device.c scsi.c usb.c ieee1394.c pcmcia.c ata.c sdhci.c ../unix/hello.c - ../unix/network.c ../unix/unix.c) + ../unix/network.c ../unix/unix.c mmc/ioctl.h) CHECK_LIBRARY_EXISTS("udev" udev_new "" HAS_UDEV) CHECK_INCLUDE_FILES("linux/mmc/ioctl.h" HAVE_MMC_IOCTL_H) diff --git a/linux/mmc/ioctl.h b/linux/mmc/ioctl.h new file mode 100644 index 0000000..c8e37b5 --- /dev/null +++ b/linux/mmc/ioctl.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ + +#ifndef DICREMOTE_LINUX_MMC_IOCTL_H_ +#define DICREMOTE_LINUX_MMC_IOCTL_H_ + +#ifdef HAS_UAPI_MMC +#include +#include +#else +#include + +#ifndef MMC_BLOCK_MAJOR +#define MMC_BLOCK_MAJOR 179 +#endif + +struct mmc_ioc_cmd +{ + /* + * Direction of data: nonzero = write, zero = read. + * Bit 31 selects 'Reliable Write' for RPMB. + */ + int write_flag; + + /* Application-specific command. true = precede with CMD55 */ + int is_acmd; + + uint32_t opcode; + uint32_t arg; + uint32_t response[4]; /* CMD response */ + unsigned int flags; + unsigned int blksz; + unsigned int blocks; + + /* + * Sleep at least postsleep_min_us useconds, and at most + * postsleep_max_us useconds *after* issuing command. Needed for + * some read commands for which cards have no other way of indicating + * they're ready for the next command (i.e. there is no equivalent of + * a "busy" indicator for read operations). + */ + unsigned int postsleep_min_us; + unsigned int postsleep_max_us; + + /* + * Override driver-computed timeouts. Note the difference in units! + */ + unsigned int data_timeout_ns; + unsigned int cmd_timeout_ms; + + /* + * For 64-bit machines, the next member, ``__u64 data_ptr``, wants to + * be 8-byte aligned. Make sure this struct is the same size when + * built for 32-bit. + */ + uint32_t __pad; + + /* DAT buffer */ + uint64_t data_ptr; +}; +#define mmc_ioc_cmd_set_data(ic, ptr) ic.data_ptr = (__u64)(unsigned long)ptr + +/** + * struct mmc_ioc_multi_cmd - multi command information + * @num_of_cmds: Number of commands to send. Must be equal to or less than + * MMC_IOC_MAX_CMDS. + * @cmds: Array of commands with length equal to 'num_of_cmds' + */ +struct mmc_ioc_multi_cmd +{ + uint64_t num_of_cmds; + struct mmc_ioc_cmd cmds[0]; +}; + +#define MMC_IOC_CMD _IOWR(MMC_BLOCK_MAJOR, 0, struct mmc_ioc_cmd) +/* + * MMC_IOC_MULTI_CMD: Used to send an array of MMC commands described by + * the structure mmc_ioc_multi_cmd. The MMC driver will issue all + * commands in array in sequence to card. + */ +#define MMC_IOC_MULTI_CMD _IOWR(MMC_BLOCK_MAJOR, 1, struct mmc_ioc_multi_cmd) +/* + * Since this ioctl is only meant to enhance (and not replace) normal access + * to the mmc bus device, an upper data transfer limit of MMC_IOC_MAX_BYTES + * is enforced per ioctl call. For larger data transfers, use the normal + * block device operations. + */ +#define MMC_IOC_MAX_BYTES (512L * 1024) +#define MMC_IOC_MAX_CMDS 255 + +#endif +#endif // DICREMOTE_LINUX_MMC_IOCTL_H_ diff --git a/linux/sdhci.c b/linux/sdhci.c index 65a553f..660b2bb 100644 --- a/linux/sdhci.c +++ b/linux/sdhci.c @@ -17,13 +17,10 @@ #include -#ifdef HAS_UAPI_MMC #include -#include -#include +#include "mmc/ioctl.h" #include #include -#endif int32_t LinuxSendSdhciCommand(int device_fd, uint8_t command, @@ -39,9 +36,6 @@ int32_t LinuxSendSdhciCommand(int device_fd, uint32_t* duration, uint32_t* sense) { -#ifndef HAS_UAPI_MMC - return -1; -#else struct mmc_ioc_cmd mmc_ioc_cmd; int32_t error; *duration = 0; @@ -74,5 +68,4 @@ int32_t LinuxSendSdhciCommand(int device_fd, memcpy((char*)response, (char*)&mmc_ioc_cmd.response, sizeof(uint32_t) * 4); return error; -#endif } \ No newline at end of file