Hi Stefan, Thanks for your opinion.
>-----Original Message----- >From: Stefan Roese <s...@denx.de> >Sent: 2019年9月29日 19:46 >To: Peng Ma <peng...@nxp.com>; s...@chromium.org; Prabhakar X ><prabhakar.kushw...@nxp.com>; ja...@openedev.com; >bmeng...@gmail.com; Andy Tang <andy.t...@nxp.com> >Cc: michal.si...@xilinx.com; andre.przyw...@arm.com; sm...@web.de; >u-boot@lists.denx.de; Robert Hancock <hanc...@sedsystems.ca> >Subject: [EXT] Re: [RFC 1/3] scsi: ata: Add DM SCSI interface to support None >AHCI sata driver > >Caution: EXT Email > >Hi Peng, > >On 25.09.19 11:54, Peng Ma wrote: >> In driver/ata. If the sata driver support AHCI mode, there will >> provides a complete set of SCSI interface. If the sata is not support >> AHCI >> mode(NONE_AHCI) there will not provides the SCSI interface. >> >> This patch is to support SCSI interface for None AHCI sata such as >> fsl_sata.c sil_sata.c etc. >> >> Signed-off-by: Peng Ma <peng...@nxp.com> >> --- >> drivers/ata/Kconfig | 17 +++- >> drivers/ata/Makefile | 2 + >> drivers/ata/ata-uclass.c | 16 ++++ >> drivers/ata/ata.c | 244 >+++++++++++++++++++++++++++++++++++++++++++++++ >> drivers/ata/sata.c | 2 +- >> drivers/ata/scsi_ata.h | 43 +++++++++ >> include/dm/uclass-id.h | 1 + >> 7 files changed, 323 insertions(+), 2 deletions(-) >> create mode 100644 drivers/ata/ata-uclass.c >> create mode 100644 drivers/ata/ata.c >> create mode 100644 drivers/ata/scsi_ata.h > >Please take a look at commit 0506620f4f49 ("sata: sata_mv: Add DM support >to enable CONFIG_BLK usage"). Perhaps this is a way to migrate these drivers >to DM / BLK as well. > [Peng Ma] I saw This changed is not support SCSI command. >BTW: I agree with Robert, that SCSI is a bit misleading here. We are not using >the SCSI commands on the boards with this Marvell (non-AHCI) SATA driver. >The SATA command is more appropriate in this case in my eyes. > [Peng Ma] OK, you mean There is no need to support SCSI command for Non-AHCI driver? We still use SATA command for Non-AHCI driver here? Best Regards, Peng >Thanks, >Stefan > >> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index >> 87636ae..3d6db2e 100644 >> --- a/drivers/ata/Kconfig >> +++ b/drivers/ata/Kconfig >> @@ -7,6 +7,13 @@ config AHCI >> operations at present. The block device interface has not been >converted >> to driver model. >> >> +config NONE_AHCI >> + bool "Support None AHCI SATA controllers with driver model" >> + depends on DM >> + help >> + This enables a uclass for disk controllers in U-Boot. such as AHCI. >> It >> + support None AHCI sata with DM mode >> + >> config SATA >> bool "Support SATA controllers" >> select HAVE_BLOCK_DEVICE >> @@ -32,6 +39,15 @@ config SCSI_AHCI >> help >> Enable this to allow interfacing SATA devices via the SCSI layer. >> >> +config SCSI_NONE_AHCI >> + bool "Enable SCSI interface to None AHCI SATA devices" >> + select LIBATA >> + select SCSI >> + select DM_SCSI >> + help >> + Enable this to allow interfacing None AHCI SATA devices via the DM >> + SCSI layer. >> + >> menu "SATA/SCSI device support" >> >> config AHCI_PCI >> @@ -49,7 +65,6 @@ config SATA_CEVA >> ZynqMP. Support up to 2 external devices. Complient with SATA >3.1 and >> AHCI 1.3 specifications with hot-plug detect feature. >> >> - >> config DWC_AHCI >> bool "Enable Synopsys DWC AHCI driver support" >> select SCSI_AHCI >> diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index >> 6e03384..cddbdc8 100644 >> --- a/drivers/ata/Makefile >> +++ b/drivers/ata/Makefile >> @@ -6,8 +6,10 @@ >> obj-$(CONFIG_DWC_AHCI) += dwc_ahci.o >> obj-$(CONFIG_FSL_AHCI) += fsl_ahci.o >> obj-$(CONFIG_AHCI) += ahci-uclass.o >> +obj-$(CONFIG_NONE_AHCI) += ata-uclass.o >> obj-$(CONFIG_AHCI_PCI) += ahci-pci.o >> obj-$(CONFIG_SCSI_AHCI) += ahci.o >> +obj-$(CONFIG_SCSI_NONE_AHCI) += ata.o >> obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o >> obj-$(CONFIG_FSL_SATA) += fsl_sata.o >> obj-$(CONFIG_LIBATA) += libata.o >> diff --git a/drivers/ata/ata-uclass.c b/drivers/ata/ata-uclass.c new >> file mode 100644 index 0000000..e2cc499 >> --- /dev/null >> +++ b/drivers/ata/ata-uclass.c >> @@ -0,0 +1,16 @@ >> +// SPDX-License-Identifier: GPL-2.0+ >> +/* >> + * Copyright (c) 2019 NXP, Inc >> + * Written by Peng Ma<peng...@nxp.com> */ >> + >> +#include <common.h> >> +#include <dm.h> >> +#include <scsi.h> >> +#include "scsi_ata.h" >> + >> +UCLASS_DRIVER(ata) = { >> + .id = UCLASS_NONE_AHCI, >> + .name = "ata", >> + .per_device_auto_alloc_size = sizeof(struct ata_uc_priv), }; >> diff --git a/drivers/ata/ata.c b/drivers/ata/ata.c new file mode >> 100644 index 0000000..bdb7403 >> --- /dev/null >> +++ b/drivers/ata/ata.c >> @@ -0,0 +1,244 @@ >> +// SPDX-License-Identifier: GPL-2.0+ >> +/* >> + * Copyright (C) NXP, Inc. 2019. >> + * Author: Peng Ma<peng...@nxp.com> >> + * >> + * with the reference on libata and none ahci drvier in kernel >> + * >> + * This driver provides a DM SCSI interface to None AHCI SATA. >> + */ >> + >> +#include <common.h> >> +#include <dm/lists.h> >> +#include <dm.h> >> +#include <scsi.h> >> +#include <libata.h> >> +#include <sata.h> >> +#include <malloc.h> >> +#include <memalign.h> >> +#include <fis.h> >> + >> +#include "scsi_ata.h" >> + >> +int ata_bind_scsi(struct udevice *ata_dev, struct udevice **devp) { >> + int ret; >> + struct udevice *dev; >> + >> + ret = device_bind_driver(ata_dev, "ata_scsi", "ata_scsi", &dev); >> + if (ret) >> + return ret; >> + *devp = dev; >> + >> + return 0; >> +} >> + >> +static int scsi_exec_internal(struct udevice *dev, struct scsi_cmd *pccb, >> + bool is_write) { >> + u32 temp; >> + u16 blocks = 0; >> + int ret = -ENODEV; >> + lbaint_t start = 0; >> + u8 port = pccb->target; >> + u8 *buffer = pccb->pdata; >> + struct ata_uc_priv *uc_priv = dev_get_uclass_priv(dev); >> + >> + /* Retrieve the base LBA number from the ccb structure. */ >> + if (pccb->cmd[0] == SCSI_READ16) { >> + memcpy(&start, pccb->cmd + 2, 8); >> + start = be64_to_cpu(start); >> + } else { >> + memcpy(&temp, pccb->cmd + 2, 4); >> + start = be32_to_cpu(temp); >> + } >> + >> + if (pccb->cmd[0] == SCSI_READ16) >> + blocks = (((u16)pccb->cmd[13]) << 8) | >((u16)pccb->cmd[14]); >> + else >> + blocks = (((u16)pccb->cmd[7]) << 8) | >> + ((u16)pccb->cmd[8]); >> + >> + debug("scsi_ata: %s %u blocks starting from lba 0x" LBAFU "\n", >> + is_write ? "write" : "read", blocks, start); >> + >> + if (is_write) >> + if (uc_priv->write) >> + ret = uc_priv->write(dev, start, blocks, buffer, >port); >> + else >> + pr_err("scsi_ata: write ptr is NULL\n"); >> + else >> + if (uc_priv->read) >> + ret = uc_priv->read(dev, start, blocks, buffer, >port); >> + else >> + pr_err("scsi_ata: read ptr is NULL\n"); >> + return ret; >> +} >> + >> +static char *fsl_ata_id_strcpy(u16 *target, u16 *src, int len) { >> + int i; >> + >> + for (i = 0; i < len / 2; i++) >> + target[i] = src[i]; >> + >> + return (char *)target; >> +} >> + >> +static int ata_scsiop_inquiry(struct udevice *dev, struct scsi_cmd >> +*pccb) { >> + u8 port; >> + u16 *idbuf; >> + struct ata_uc_priv *uc_priv = dev_get_uclass_priv(dev); >> + >> + ALLOC_CACHE_ALIGN_BUFFER(u16, tmpid, ATA_ID_WORDS); >> + >> + /* Clean ccb data buffer */ >> + memset(pccb->pdata, 0, pccb->datalen); >> + >> + if (pccb->datalen <= 35) >> + return 0; >> + >> + /* Read id from sata */ >> + port = pccb->target; >> + >> + if (uc_priv->ata_inquiry) { >> + uc_priv->ata_inquiry(dev, (u16 *)tmpid, port); >> + } else { >> + pr_err("scsi_ata: ata_inquiry ptr is NULL\n"); >> + return -ENODEV; >> + } >> + >> + if (!uc_priv->ataid[port]) { >> + uc_priv->ataid[port] = malloc(ATA_ID_WORDS * 2); >> + if (!uc_priv->ataid[port]) { >> + pr_err("%s: No memory for ataid[port]\n", >__func__); >> + return -ENOMEM; >> + } >> + } >> + >> + idbuf = uc_priv->ataid[port]; >> + >> + memcpy(idbuf, tmpid, ATA_ID_WORDS * 2); >> + >> + memcpy(&pccb->pdata[8], "ATA ", 8); >> + fsl_ata_id_strcpy((u16 *)&pccb->pdata[16], &idbuf[ATA_ID_PROD], >16); >> + fsl_ata_id_strcpy((u16 *)&pccb->pdata[32], >> + &idbuf[ATA_ID_FW_REV], 4); >> + >> +#ifdef DEBUG >> + ata_dump_id(idbuf); >> +#endif >> + return 0; >> +} >> + >> +/* >> + * SCSI READ CAPACITY10 command operation. >> + */ >> +static int ata_scsiop_read_capacity10(struct ata_uc_priv *uc_priv, >> + struct scsi_cmd *pccb) { >> + u32 cap; >> + u64 cap64; >> + u32 block_size; >> + >> + if (!uc_priv->ataid[pccb->target]) { >> + pr_err("scsi_ata: SCSI READ CAPACITY10 command >failure."); >> + pr_err("\tNo ATA info!\n"); >> + pr_err("\tPlease run SCSI command INQUIRY first!\n"); >> + return -EPERM; >> + } >> + >> + cap64 = ata_id_n_sectors(uc_priv->ataid[pccb->target]); >> + if (cap64 > 0x100000000ULL) >> + cap64 = 0xffffffff; >> + >> + cap = cpu_to_be32(cap64); >> + memcpy(pccb->pdata, &cap, sizeof(cap)); >> + >> + block_size = cpu_to_be32((u32)512); >> + memcpy(&pccb->pdata[4], &block_size, 4); >> + >> + return 0; >> +} >> + >> +/* >> + * SCSI READ CAPACITY16 command operation. >> + */ >> +static int ata_scsiop_read_capacity16(struct ata_uc_priv *uc_priv, >> + struct scsi_cmd *pccb) { >> + u64 cap; >> + u64 block_size; >> + >> + if (!uc_priv->ataid[pccb->target]) { >> + pr_err("scsi_ata: SCSI READ CAPACITY16 command >failure."); >> + pr_err("\tNo ATA info!\n"); >> + pr_err("\tPlease run SCSI command INQUIRY first!\n"); >> + return -EPERM; >> + } >> + >> + cap = ata_id_n_sectors(uc_priv->ataid[pccb->target]); >> + cap = cpu_to_be64(cap); >> + memcpy(pccb->pdata, &cap, sizeof(cap)); >> + >> + block_size = cpu_to_be64((u64)512); >> + memcpy(&pccb->pdata[8], &block_size, 8); >> + >> + return 0; >> +} >> + >> +/* >> + * SCSI TEST UNIT READY command operation. >> + */ >> +static int ata_scsiop_test_unit_ready(struct ata_uc_priv *uc_priv, >> + struct scsi_cmd *pccb) { >> + return (uc_priv->ataid[pccb->target]) ? 0 : -EPERM; } >> + >> +static int ata_scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) >> +{ >> + struct ata_uc_priv *uc_priv = dev_get_uclass_priv(dev->parent); >> + int ret; >> + >> + switch (pccb->cmd[0]) { >> + case SCSI_READ16: >> + case SCSI_READ10: >> + ret = scsi_exec_internal(dev->parent, pccb, 0); >> + break; >> + case SCSI_WRITE10: >> + ret = scsi_exec_internal(dev->parent, pccb, 1); >> + break; >> + case SCSI_RD_CAPAC10: >> + ret = ata_scsiop_read_capacity10(uc_priv, pccb); >> + break; >> + case SCSI_RD_CAPAC16: >> + ret = ata_scsiop_read_capacity16(uc_priv, pccb); >> + break; >> + case SCSI_TST_U_RDY: >> + ret = ata_scsiop_test_unit_ready(uc_priv, pccb); >> + break; >> + case SCSI_INQUIRY: >> + ret = ata_scsiop_inquiry(dev->parent, pccb); >> + break; >> + default: >> + pr_err("Unsupport SCSI command 0x%02x\n", >pccb->cmd[0]); >> + return -ENOTSUPP; >> + } >> + >> + if (ret) { >> + debug("SCSI command 0x%02x ret errno %d\n", >pccb->cmd[0], ret); >> + return ret; >> + } >> + >> + return 0; >> +} >> + >> +struct scsi_ops ata_scsi_ops = { >> + .exec = ata_scsi_exec, >> +}; >> + >> +U_BOOT_DRIVER(ata_scsi) = { >> + .name = "ata_scsi", >> + .id = UCLASS_SCSI, >> + .ops = &ata_scsi_ops, >> +}; >> diff --git a/drivers/ata/sata.c b/drivers/ata/sata.c index >> e384b80..1fee375 100644 >> --- a/drivers/ata/sata.c >> +++ b/drivers/ata/sata.c >> @@ -83,7 +83,7 @@ static unsigned long sata_bwrite(struct blk_desc >*block_dev, lbaint_t start, >> } >> #endif >> >> -#ifndef CONFIG_AHCI >> +#ifndef CONFIG_SCSI >> int __sata_initialize(void) >> { >> int rc, ret = -1; >> diff --git a/drivers/ata/scsi_ata.h b/drivers/ata/scsi_ata.h new file >> mode 100644 index 0000000..472a562 >> --- /dev/null >> +++ b/drivers/ata/scsi_ata.h >> @@ -0,0 +1,43 @@ >> +/* SPDX-License-Identifier: GPL-2.0+ */ >> +/* >> + * Copyright (C) NXP Inc. 2019. >> + * Author: Peng Ma<peng...@nxp.com> >> + */ >> +#ifndef _AHCI_H_ >> +#define _AHCI_H_ >> + >> +#include <pci.h> >> + >> +#define ATA_MAX_PORTS 32 >> +/** >> + * struct ata_uc_priv - information about an ATA controller >> + * >> + * When driver model is used, this is accessible using >> +dev_get_uclass_priv(dev) >> + * where dev is the controller (although at present it sometimes stands >alone). >> + */ >> +struct ata_uc_priv { >> +#if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI) >> + struct udevice *dev; >> +#else >> + pci_dev_t dev; >> +#endif >> + u16 *ataid[ATA_MAX_PORTS]; >> + >> + ulong (*read)(struct udevice *dev, lbaint_t start, u16 blkcnt, >> + void *buffer, u8 port); >> + ulong (*write)(struct udevice *dev, lbaint_t start, u16 blkcnt, >> + const void *buffer, u8 port); >> + int (*ata_inquiry)(struct udevice *dev, u16 *buffer, u8 port); >> +}; >> + >> +/** >> + * ata_bind_scsi() - bind a new SCSI bus as a child >> + * >> + * Note that the SCSI bus device will itself bind block devices >> + * >> + * @ahci_dev: AHCI parent device >> + * @devp: Returns new SCSI bus device >> + * @return 0 if OK, -ve on error >> + */ >> +int ata_bind_scsi(struct udevice *ahci_dev, struct udevice **devp); >> +#endif >> diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index >> d4d9610..087cd2d 100644 >> --- a/include/dm/uclass-id.h >> +++ b/include/dm/uclass-id.h >> @@ -29,6 +29,7 @@ enum uclass_id { >> /* U-Boot uclasses start here - in alphabetical order */ >> UCLASS_ADC, /* Analog-to-digital converter */ >> UCLASS_AHCI, /* SATA disk controller */ >> + UCLASS_NONE_AHCI, /* SATA disk controller of None AHCI */ >> UCLASS_AUDIO_CODEC, /* Audio codec with control and data >path */ >> UCLASS_AXI, /* AXI bus */ >> UCLASS_BLK, /* Block device */ >> > >Viele Grüße, >Stefan > >-- >DENX Software Engineering GmbH, Managing Director: Wolfgang Denk >HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany >Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: s...@denx.de _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot