diff --git a/drivers/misc/rpmsgblk.c b/drivers/misc/rpmsgblk.c index be03f009c1..5817994ae3 100644 --- a/drivers/misc/rpmsgblk.c +++ b/drivers/misc/rpmsgblk.c @@ -87,7 +87,7 @@ static ssize_t rpmsgblk_write(FAR struct inode *inode, blkcnt_t start_sector, unsigned int nsectors); static int rpmsgblk_geometry(FAR struct inode *inode, FAR struct geometry *geometry); -static ssize_t rpmsgblk_ioctl_arglen(int cmd, unsigned long arg); +static ssize_t rpmsgblk_ioctl_arglen(int cmd); static int rpmsgblk_ioctl(FAR struct inode *inode, int cmd, unsigned long arg); #ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS @@ -491,7 +491,7 @@ out: * ****************************************************************************/ -static ssize_t rpmsgblk_ioctl_arglen(int cmd, unsigned long arg) +static ssize_t rpmsgblk_ioctl_arglen(int cmd) { switch (cmd) { @@ -516,37 +516,130 @@ static ssize_t rpmsgblk_ioctl_arglen(int cmd, unsigned long arg) return sizeof(struct partition_info_s); case BIOC_BLKSSZGET: return sizeof(blksize_t); - case MMC_IOC_CMD: - { - FAR struct mmc_ioc_cmd *ioc = - (FAR struct mmc_ioc_cmd *)(uintptr_t)arg; - - return sizeof(struct mmc_ioc_cmd) + ioc->blksz * ioc->blocks; - } - - case MMC_IOC_MULTI_CMD: - { - FAR struct mmc_ioc_multi_cmd *mioc = - (FAR struct mmc_ioc_multi_cmd *)(uintptr_t)arg; - uint64_t num = mioc->num_of_cmds; - uint64_t i; - ssize_t arglen; - - arglen = sizeof(struct mmc_ioc_multi_cmd) + - num * sizeof(struct mmc_ioc_cmd); - for (i = 0; i < num; i++) - { - arglen += mioc->cmds[i].blksz * mioc->cmds[i].blocks; - } - - return arglen; - } - default: return -ENOTTY; } } +/**************************************************************************** + * Name: rpmsgblk_mmc_cmd_ioctl + * + * Description: + * If args include a usrspace buffer pointer, then the content of this + * pointer should also be copied into share memory and set after args. + * + ****************************************************************************/ + +static int rpmsgblk_mmc_cmd_ioctl(FAR struct inode *inode, unsigned long arg) +{ + FAR struct rpmsgblk_s *priv = inode->i_private; + FAR struct mmc_ioc_cmd *ioc = (FAR struct mmc_ioc_cmd *)(uintptr_t)arg; + FAR struct rpmsgblk_ioctl_s *msg; + uint32_t space; + ssize_t msglen; + + msglen = sizeof(*msg) + sizeof(struct mmc_ioc_cmd) + + ioc->blksz * ioc->blocks - 1; + + msg = rpmsgblk_get_tx_payload_buffer(priv, &space); + if (msg == NULL) + { + return -ENOMEM; + } + + DEBUGASSERT(space > msglen); + + msg->request = MMC_IOC_CMD; + msg->arg = arg; + msg->arglen = sizeof(struct mmc_ioc_cmd) + ioc->blksz * ioc->blocks; + + memcpy(msg->buf, ioc, sizeof(*ioc)); + if (ioc->data_ptr) + { + memcpy(msg->buf + sizeof(*ioc), (FAR void *)(uintptr_t)ioc->data_ptr, + ioc->blksz * ioc->blocks); + } + + return rpmsgblk_send_recv(priv, RPMSGBLK_IOCTL, false, &msg->header, + msglen, ioc); +} + +/**************************************************************************** + * Name: rpmsgblk_mmc_multi_cmd_ioctl + * + * Description: + * The size of MMC_IOC_MILTI_CMD's memory occupation is likely to be + * larger than that allocated by rpmsgblk_get_tx_payload_buffer, which + * is not allowed by current implement. So split the mmc_ioc_multi_cmd + * into mmc_ioc_cmds to transfer. + * + ****************************************************************************/ + +static int rpmsgblk_mmc_multi_cmd_ioctl(FAR struct inode *inode, + unsigned long arg) +{ + FAR struct mmc_ioc_multi_cmd *mioc = + (FAR struct mmc_ioc_multi_cmd *)(uintptr_t)arg; + int ret = 0; + uint64_t i; + + for (i = 0; i < mioc->num_of_cmds; i++) + { + ret = rpmsgblk_mmc_cmd_ioctl(inode, + (unsigned long)(uintptr_t)&mioc->cmds[i]); + if (ret < 0) + { + return ret; + } + } + + return ret; +} + +/**************************************************************************** + * Name: rpmsgblk_default_ioctl + ****************************************************************************/ + +static int rpmsgblk_default_ioctl(FAR struct inode *inode, int cmd, + unsigned long arg) +{ + FAR struct rpmsgblk_s *priv = inode->i_private; + FAR struct rpmsgblk_ioctl_s *msg; + uint32_t space; + ssize_t arglen; + size_t msglen; + + /* Call our internal routine to perform the ioctl */ + + arglen = rpmsgblk_ioctl_arglen(cmd); + if (arglen < 0) + { + return arglen; + } + + msglen = sizeof(*msg) + arglen - 1; + + msg = rpmsgblk_get_tx_payload_buffer(priv, &space); + if (msg == NULL) + { + return -ENOMEM; + } + + DEBUGASSERT(space > msglen); + + msg->request = cmd; + msg->arg = arg; + msg->arglen = arglen; + + if (arglen > 0) + { + memcpy(msg->buf, (FAR void *)(uintptr_t)arg, arglen); + } + + return rpmsgblk_send_recv(priv, RPMSGBLK_IOCTL, false, &msg->header, + msglen, arglen > 0 ? (FAR void *)arg : NULL); +} + /**************************************************************************** * Name: rpmsgblk_ioctl * @@ -567,90 +660,22 @@ static int rpmsgblk_ioctl(FAR struct inode *inode, int cmd, unsigned long arg) { FAR struct rpmsgblk_s *priv = inode->i_private; - FAR struct rpmsgblk_ioctl_s *msg; - uint32_t space; - ssize_t arglen; - size_t msglen; /* Sanity checks */ DEBUGASSERT(priv != NULL); - if (cmd == BIOC_GEOMETRY) + switch (cmd) { - return rpmsgblk_geometry(inode, (FAR struct geometry *)arg); + case BIOC_GEOMETRY: + return rpmsgblk_geometry(inode, (FAR struct geometry *)arg); + case MMC_IOC_CMD: + return rpmsgblk_mmc_cmd_ioctl(inode, arg); + case MMC_IOC_MULTI_CMD: + return rpmsgblk_mmc_multi_cmd_ioctl(inode, arg); + default: + return rpmsgblk_default_ioctl(inode, cmd, arg); } - - /* Call our internal routine to perform the ioctl */ - - arglen = rpmsgblk_ioctl_arglen(cmd, arg); - if (arglen < 0) - { - return arglen; - } - - msglen = sizeof(*msg) + arglen - 1; - - msg = rpmsgblk_get_tx_payload_buffer(priv, &space); - if (msg == NULL) - { - return -ENOMEM; - } - - DEBUGASSERT(space > msglen); - - msg->request = cmd; - msg->arg = arg; - msg->arglen = arglen; - - if (arglen > 0) - { - /* If args include a usrspace buffer pointer, then the content of this - * pointer should also be copied into share memory and set after args. - */ - - if (cmd == MMC_IOC_CMD) - { - FAR struct mmc_ioc_cmd *ioc = - (FAR struct mmc_ioc_cmd *)(uintptr_t)arg; - - memcpy(msg->buf, (FAR void *)(uintptr_t)arg, sizeof(*ioc)); - if (ioc->data_ptr) - { - memcpy(msg->buf + sizeof(*ioc), - (FAR void *)(uintptr_t)ioc->data_ptr, - ioc->blksz * ioc->blocks); - } - } - else if (cmd == MMC_IOC_MULTI_CMD) - { - FAR struct mmc_ioc_multi_cmd *mioc = - (FAR struct mmc_ioc_multi_cmd *)(uintptr_t)arg; - uint64_t num = mioc->num_of_cmds; - ssize_t copy = sizeof(struct mmc_ioc_multi_cmd) + - num * sizeof(struct mmc_ioc_cmd); - uint64_t i; - - memcpy(msg->buf, (FAR void *)(uintptr_t)arg, copy); - for (i = 0; i < num; i++) - { - if (mioc->cmds[i].data_ptr) - { - memcpy(msg->buf + copy, - (FAR void *)(uintptr_t)mioc->cmds[i].data_ptr, - mioc->cmds[i].blksz * mioc->cmds[i].blocks); - copy += mioc->cmds[i].blksz * mioc->cmds[i].blocks; - } - } - } - else - { - memcpy(msg->buf, (FAR void *)(uintptr_t)arg, arglen); - } - } - - return rpmsgblk_send_recv(priv, RPMSGBLK_IOCTL, false, &msg->header, - msglen, arglen > 0 ? (FAR void *)arg : NULL); } /**************************************************************************** @@ -952,33 +977,6 @@ static int rpmsgblk_ioctl_handler(FAR struct rpmsg_endpoint *ept, } break; - case MMC_IOC_MULTI_CMD: - { - FAR struct mmc_ioc_multi_cmd *mioc = - (FAR struct mmc_ioc_multi_cmd *)(uintptr_t)cookie->data; - FAR struct mmc_ioc_multi_cmd *mioc_rsp = - (FAR struct mmc_ioc_multi_cmd *)(uintptr_t)rsp->buf; - uint64_t num = mioc->num_of_cmds; - size_t off = sizeof(struct mmc_ioc_multi_cmd) + - num * sizeof(struct mmc_ioc_cmd); - uint64_t i; - - for (i = 0; i < num; i++) - { - memcpy(&mioc->cmds[i], &mioc_rsp->cmds[i], - sizeof(struct mmc_ioc_cmd) - - sizeof(mioc->cmds[i].data_ptr)); - if (mioc->cmds[i].data_ptr) - { - memcpy((FAR void *)(uintptr_t)mioc->cmds[i].data_ptr, - rsp->buf + off, - mioc->cmds[i].blksz * mioc->cmds[i].blocks); - off += mioc->cmds[i].blksz * mioc->cmds[i].blocks; - } - } - } - break; - default: memcpy(cookie->data, rsp->buf, rsp->arglen); break; diff --git a/drivers/misc/rpmsgblk_server.c b/drivers/misc/rpmsgblk_server.c index b8a304df1d..b8c0f050a2 100644 --- a/drivers/misc/rpmsgblk_server.c +++ b/drivers/misc/rpmsgblk_server.c @@ -345,27 +345,6 @@ static int rpmsgblk_ioctl_handler(FAR struct rpmsg_endpoint *ept, } break; - case MMC_IOC_MULTI_CMD: - { - FAR struct mmc_ioc_multi_cmd *mioc = - (FAR struct mmc_ioc_multi_cmd *)(uintptr_t)msg->buf; - uint64_t num = mioc->num_of_cmds; - size_t off = sizeof(struct mmc_ioc_multi_cmd) + - num * sizeof(struct mmc_ioc_cmd); - uint64_t i; - - for (i = 0; i < num; i++) - { - if (mioc->cmds[i].data_ptr) - { - mioc->cmds[i].data_ptr = (uint64_t)(uintptr_t) - ((FAR uint8_t *)mioc + off); - off += mioc->cmds[i].blksz * mioc->cmds[i].blocks; - } - } - } - break; - default: break; }