From f11b5c52f3068f38e2f58a2db39469fbb944c6e3 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Mon, 17 Feb 2025 15:28:36 +0300 Subject: [PATCH 1/4] scsi_lib: divide data_read_write_10 into two functions --- os/various/lib_scsi.c | 59 +++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/os/various/lib_scsi.c b/os/various/lib_scsi.c index 64bd7b5b..1788524e 100644 --- a/os/various/lib_scsi.c +++ b/os/various/lib_scsi.c @@ -340,7 +340,7 @@ static bool data_overflow(SCSITarget *scsip, const data_request_t *req) { } /** - * @brief SCSI read/write (10) command handler. + * @brief SCSI read (10) command handler. * * @param[in] scsip pointer to @p SCSITarget structure * @param[in] cmd pointer to SCSI command data @@ -349,7 +349,45 @@ static bool data_overflow(SCSITarget *scsip, const data_request_t *req) { * * @notapi */ -static bool data_read_write10(SCSITarget *scsip, const uint8_t *cmd) { +static bool data_read10(SCSITarget *scsip, const uint8_t *cmd) { + data_request_t req = decode_data_request(cmd); + + if (data_overflow(scsip, &req)) { + return SCSI_FAILED; + } + else { + const SCSITransport *tr = scsip->config->transport; + BaseBlockDevice *blkdev = scsip->config->blkdev; + BlockDeviceInfo bdi; + blkGetInfo(blkdev, &bdi); + size_t bs = bdi.blk_size; + uint8_t *buf = scsip->config->blkbuf; + uint32_t n_bufs = scsip->config->blkbufsize / bs; + + size_t i = 0; + while (i < req.blk_cnt) { + size_t n = n_bufs > (req.blk_cnt - i) ? (req.blk_cnt - i) : n_bufs; + + // TODO: block error handling + blkRead(blkdev, req.first_lba + i, buf, n); + tr->transmit(tr, buf, bs * n); + i += n; + } + } + return SCSI_SUCCESS; +} + +/** + * @brief SCSI write (10) command handler. + * + * @param[in] scsip pointer to @p SCSITarget structure + * @param[in] cmd pointer to SCSI command data + * + * @return The operation status. + * + * @notapi + */ +static bool data_write10(SCSITarget *scsip, const uint8_t *cmd) { data_request_t req = decode_data_request(cmd); @@ -369,16 +407,9 @@ static bool data_read_write10(SCSITarget *scsip, const uint8_t *cmd) { while (i < req.blk_cnt) { size_t n = n_bufs > (req.blk_cnt - i) ? (req.blk_cnt - i) : n_bufs; - if (cmd[0] == SCSI_CMD_READ_10) { - // TODO: block error handling - blkRead(blkdev, req.first_lba + i, buf, n); - tr->transmit(tr, buf, bs * n); - } - else { - // TODO: block error handling - tr->receive(tr, buf, bs * n); - blkWrite(blkdev, req.first_lba + i, buf, n); - } + // TODO: block error handling + tr->receive(tr, buf, bs * n); + blkWrite(blkdev, req.first_lba + i, buf, n); i += n; } } @@ -448,12 +479,12 @@ bool scsiExecCmd(SCSITarget *scsip, const uint8_t *cmd) { case SCSI_CMD_READ_10: dbgprintf("SCSI_CMD_READ_10\r\n"); - ret = data_read_write10(scsip, cmd); + ret = data_read10(scsip, cmd); break; case SCSI_CMD_WRITE_10: dbgprintf("SCSI_CMD_WRITE_10\r\n"); - ret = data_read_write10(scsip, cmd); + ret = data_write10(scsip, cmd); break; case SCSI_CMD_TEST_UNIT_READY: From d325ff1c2f058faefefaad0c120b4433d2259cb8 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Mon, 17 Feb 2025 15:30:04 +0300 Subject: [PATCH 2/4] scsi_lib: transmit_wait hook --- os/various/lib_scsi.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/os/various/lib_scsi.h b/os/various/lib_scsi.h index b878eeea..a690f620 100644 --- a/os/various/lib_scsi.h +++ b/os/various/lib_scsi.h @@ -187,9 +187,15 @@ typedef struct PACKED_VAR { */ typedef uint32_t (*scsi_transport_transmit_t)(const SCSITransport *transport, const uint8_t *data, size_t len); +/** + * @brief Type of a SCSI transport transmit finish wait call. + * + * @param[in] usbp pointer to the @p SCSITransport object + */ +typedef uint32_t (*scsi_transport_wait_transmit_t)(const SCSITransport *transport); /** - * @brief Type of a SCSI transport transmit call. + * @brief Type of a SCSI transport receive call. * * @param[in] usbp pointer to the @p SCSITransport object * @param[out] data pointer to receive buffer @@ -206,6 +212,10 @@ struct SCSITransport { * @brief Transmit call provided by lower level driver. */ scsi_transport_transmit_t transmit; + /** + * @brief Transmit wait call provided by lower level driver. + */ + scsi_transport_wait_transmit_t transmit_wait; /** * @brief Receive call provided by lower level driver. */ From 9c2a208a3cb94e59bb78835543943889a9703d86 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Tue, 18 Feb 2025 11:20:02 +0300 Subject: [PATCH 3/4] lib_scsi: non-blocking transmit start hook --- os/various/lib_scsi.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/os/various/lib_scsi.h b/os/various/lib_scsi.h index a690f620..8dde81c5 100644 --- a/os/various/lib_scsi.h +++ b/os/various/lib_scsi.h @@ -212,6 +212,10 @@ struct SCSITransport { * @brief Transmit call provided by lower level driver. */ scsi_transport_transmit_t transmit; + /** + * @brief Transmit call provided by lower level driver. + */ + scsi_transport_transmit_t transmit_start; /** * @brief Transmit wait call provided by lower level driver. */ From 420eec8f4ccd8e461791daf293201dcd0befbba4 Mon Sep 17 00:00:00 2001 From: Andrey Gusakov Date: Tue, 18 Feb 2025 11:19:15 +0300 Subject: [PATCH 4/4] lib_scsi: use non-blocking USB API and double buffering mode If available --- os/various/lib_scsi.c | 44 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/os/various/lib_scsi.c b/os/various/lib_scsi.c index 1788524e..f50418b7 100644 --- a/os/various/lib_scsi.c +++ b/os/various/lib_scsi.c @@ -365,13 +365,45 @@ static bool data_read10(SCSITarget *scsip, const uint8_t *cmd) { uint32_t n_bufs = scsip->config->blkbufsize / bs; size_t i = 0; - while (i < req.blk_cnt) { - size_t n = n_bufs > (req.blk_cnt - i) ? (req.blk_cnt - i) : n_bufs; + if ((n_bufs > 1) && (tr->transmit_start) && (tr->transmit_wait)) { + // double buffering mode + while (i < req.blk_cnt) { + size_t n = n_bufs > (req.blk_cnt - i) ? (req.blk_cnt - i) : n_bufs; + size_t first_n = (n + 1) / 2; + size_t second_n = n - first_n; - // TODO: block error handling - blkRead(blkdev, req.first_lba + i, buf, n); - tr->transmit(tr, buf, bs * n); - i += n; + // read first half of buffer + // TODO: block error handling + blkRead(blkdev, req.first_lba + i, buf, first_n); + + // TODO: block error handling + tr->transmit_wait(tr); + tr->transmit_start(tr, buf, bs * first_n); + + i += first_n; + + if (second_n) { + // read second half of buffer while first are transfered over USB + // TODO: block error handling + blkRead(blkdev, req.first_lba + i, buf + bs * first_n, second_n); + + // TODO: block error handling + tr->transmit_wait(tr); + tr->transmit_start(tr, buf + bs * first_n, bs * second_n); + + i += second_n; + } + } + tr->transmit_wait(tr); + } else { + while (i < req.blk_cnt) { + size_t n = n_bufs > (req.blk_cnt - i) ? (req.blk_cnt - i) : n_bufs; + + // TODO: block error handling + blkRead(blkdev, req.first_lba + i, buf, n); + tr->transmit(tr, buf, bs * n); + i += n; + } } } return SCSI_SUCCESS;