Hi Varadarajan, On Mon, 24 Mar 2025 at 04:02, Varadarajan Narayanan <[email protected]> wrote: > > UFS devices uses the block and scsi frameworks. Enable UFS erase > support by adding erase support to SCSI. > > Signed-off-by: Varadarajan Narayanan <[email protected]> > --- > cmd/scsi.c | 3 +- > drivers/scsi/scsi.c | 92 +++++++++++++++++++++++++++++++++++++++++++++ > include/scsi.h | 13 +++++++ > 3 files changed, 107 insertions(+), 1 deletion(-) > > diff --git a/cmd/scsi.c b/cmd/scsi.c > index c286bdc0726..9f7613424e5 100644 > --- a/cmd/scsi.c > +++ b/cmd/scsi.c > @@ -60,7 +60,8 @@ U_BOOT_CMD( > "scsi read addr blk# cnt - read `cnt' blocks starting at block > `blk#'\n" > " to memory address `addr'\n" > "scsi write addr blk# cnt - write `cnt' blocks starting at block\n" > - " `blk#' from memory address `addr'" > + " `blk#' from memory address `addr'\n" > + "scsi erase blk# cnt - erase `cnt' blocks starting at block `blk#'" > ); > > U_BOOT_CMD( > diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c > index cd0b84c0622..dc93392642d 100644 > --- a/drivers/scsi/scsi.c > +++ b/drivers/scsi/scsi.c > @@ -28,6 +28,10 @@ DEFINE_CACHE_ALIGN_BUFFER(u8, tempbuff, 512); /* > temporary data buffer */ > #define SCSI_MAX_BLK 0xFFFF > #define SCSI_LBA48_READ 0xFFFFFFF > > +#define SCSI_UNMAP_PARAM_RESERVED 0 > +#define SCSI_UNMAP_PARAM_LEN 22 > +#define SCSI_UNMAP_PARAM_DATA_LEN 16 > + > static void scsi_print_error(struct scsi_cmd *pccb) > { > /* Dummy function that could print an error for debugging */ > @@ -121,6 +125,51 @@ static void scsi_setup_write_ext(struct scsi_cmd *pccb, > lbaint_t start, > pccb->cmd[7], pccb->cmd[8]); > } > > +static void scsi_setup_erase_ext(struct scsi_cmd *pccb, lbaint_t start, > + unsigned short blocks) > +{ > + u8 *param = tempbuff; > + const u8 param_size = 24; > + > + memset(param, 0, param_size); > + param[0] = SCSI_UNMAP_PARAM_RESERVED; > + param[1] = SCSI_UNMAP_PARAM_LEN; > + param[2] = SCSI_UNMAP_PARAM_RESERVED; > + param[3] = SCSI_UNMAP_PARAM_DATA_LEN; > + > + param[8] = 0x0; > + param[9] = 0x0; > + param[10] = 0x0; > + param[11] = 0x0; > + param[12] = (start >> 24) & 0xff; > + param[13] = (start >> 16) & 0xff; > + param[14] = (start >> 8) & 0xff; > + param[15] = (start) & 0xff; > + param[16] = (blocks >> 24) & 0xff; > + param[17] = (blocks >> 16) & 0xff; > + param[18] = (blocks >> 8) & 0xff; > + param[19] = (blocks) & 0xff; > + > + memset(pccb->cmd, 0, sizeof(pccb->cmd)); > + pccb->cmd[0] = SCSI_UNMAP; > + pccb->cmd[1] = 0; > + pccb->cmd[6] = 0; > + pccb->cmd[7] = 0; > + pccb->cmd[8] = param_size; > + pccb->cmd[9] = 0; > + pccb->cmdlen = 10; > + > + pccb->pdata = param; > + pccb->datalen = param_size; > + pccb->dma_dir = DMA_TO_DEVICE; > + > + debug("%s: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt > %02X%02X\n", > + __func__, > + pccb->cmd[0], pccb->cmd[1], > + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], > + pccb->cmd[7], pccb->cmd[8]); > +} > + > static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, > void *buffer) > { > @@ -245,6 +294,48 @@ static ulong scsi_write(struct udevice *dev, lbaint_t > blknr, lbaint_t blkcnt, > return blkcnt; > } > > +/******************************************************************************* > + * scsi_erase > + */ > +static ulong scsi_erase(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt) > +{ > + struct blk_desc *block_dev = dev_get_uclass_plat(dev); > + struct udevice *bdev = dev->parent; > + struct scsi_plat *uc_plat = dev_get_uclass_plat(bdev); > + lbaint_t start, blks, max_blks; > + struct scsi_cmd *pccb = (struct scsi_cmd *)&tempccb; > + > + /* Setup device */ > + pccb->target = block_dev->target; > + pccb->lun = block_dev->lun; > + start = blknr; > + blks = blkcnt; > + if (uc_plat->max_bytes_per_req) > + max_blks = uc_plat->max_bytes_per_req / block_dev->blksz; > + else > + max_blks = SCSI_MAX_BLK; > + > + debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF "\n", > + __func__, block_dev->devnum, start, blks); > + do { > + if (blks > max_blks) { > + scsi_setup_erase_ext(pccb, start, max_blks); > + start += max_blks; > + blks -= max_blks; > + } else { > + scsi_setup_erase_ext(pccb, start, blks); > + start += blks; > + blks = 0; > + } > + if (scsi_exec(bdev, pccb)) { > + scsi_print_error(pccb); > + blkcnt -= blks; > + break; > + } > + } while (blks != 0); > + return blkcnt; > +} > + > #if IS_ENABLED(CONFIG_BOUNCE_BUFFER) > static int scsi_buffer_aligned(struct udevice *dev, struct bounce_buffer > *state) > { > @@ -592,6 +683,7 @@ int scsi_scan(bool verbose) > static const struct blk_ops scsi_blk_ops = { > .read = scsi_read, > .write = scsi_write, > + .erase = scsi_erase, > #if IS_ENABLED(CONFIG_BOUNCE_BUFFER) > .buffer_aligned = scsi_buffer_aligned, > #endif /* CONFIG_BOUNCE_BUFFER */ > diff --git a/include/scsi.h b/include/scsi.h > index b18ae37b861..d6b6e6b665f 100644 > --- a/include/scsi.h > +++ b/include/scsi.h > @@ -9,6 +9,7 @@ > #include <asm/cache.h> > #include <bouncebuf.h> > #include <linux/dma-direction.h> > +#include <part.h> > > struct udevice; > > @@ -181,6 +182,7 @@ struct scsi_cmd { > #define SCSI_WRT_VERIFY 0x2E /* Write and Verify (O) */ > #define SCSI_WRITE_LONG 0x3F /* Write Long (O) */ > #define SCSI_WRITE_SAME 0x41 /* Write Same (O) */ > +#define SCSI_UNMAP 0x42 /* Write 10-Byte (MANDATORY) */ > > /** > * enum scsi_cmd_phase - current phase of the SCSI protocol > @@ -349,6 +351,17 @@ int scsi_scan(bool verbose); > */ > int scsi_scan_dev(struct udevice *dev, bool verbose); > > +/** > + * scsi_get_blk() - Provides SCSI partition information. > + * > + * @partition_name: Partition name for fetching its info > + * @blk_desc_ptr: Provides the blk descriptor > + * @part_info_ptr: Provides partition info > + */ > +int scsi_get_blk(const char *partition_name, > + struct blk_desc **blk_desc_ptr, > + struct disk_partition *part_info_ptr); > + > #define SCSI_IDENTIFY 0xC0 /* not used */ > > /* Hardware errors */ > -- > 2.34.1 >
For testing purposes, could you please implement this method in drivers/scsi/sandbox_scsi.c() and then try to erase the block in test/dm/scsi.c ? Regards, Simon

