[U-Boot] [PATCH v2 00/44] dm: blk: Add more driver-model support for block devices

This series adjusts the block device code to support conversion to driver model. Specifically
- A new 'legacy' block interface is created, allowing block devices to be defined by a linker list and accessed through function calls - Block device commands (such as sata and scsi) are adjusted to use these functions rather than the block device array directly - These same function calls are then implemented by the block uclass - The existing block-device table in part.c is dropped - The opportunity is taken to clean up the code style, as block devices are one of the few remaining dark corners in U-Boot
It is useful to enable all block device drivers with sandbox. This improves sandbox code coverage and allows tests to be written. The following are enabled by this series:
- IDE - SCSI - SATA - Systemace
USB was already enabled. MMC will be enabled by a future series. Note that these devices do not actually function in sandbox, but the code is compiled.
As mentioned, future work will enable MMC for sandbox including adding rudimentary sandbox SD card emulation. It would also be possible to create emulations for IDE, SCSI, SATA and Systemace but that work is not planned.
It should be noted that the current CONFIG_DM_MMC option does not fully enable driver model for MMC, since the MMC operations are not running through driver model. This will need to be addressed at some point.
This series is available at u-boot-dm/blka-working
Changes in v2: - Tweak the cast - Make the string functions empty, since the implementation is not useful - Drop the code inside '#if 0' - Adjust newline output in blk_list_part() - Mention MMC partition 0 in the comments - Update the commit message to indicate that IDE doesn't work on sandbox
Simon Glass (44): Revert "dm: sandbox: Drop the pre-DM host implementation" dm: sandbox: Add a board for sandbox without CONFIG_BLK pci: Drop CONFIG_SYS_SCSI_SCAN_BUS_REVERSE dm: Rename disk uclass to ahci Allow iotrace byte access to use an address of any size sandbox: Add string and 16-bit I/O functions sandbox: Add dummy SCSI functions sandbox: Add dummy SATA functions dm: scsi: Remove the forward declarations dm: scsi: Fix up code style dm: ide: Correct various code style problems dm: ide: Remove the forward declarations dm: sata: Fix code style problems in cmd/sata.c dm: scsi: Rename CONFIG_CMD_SCSI to CONFIG_SCSI dm: blk: Add a legacy block interface dm: systemace: Add a legacy block interface dm: sandbox: Add a legacy host block interface dm: usb: Add a legacy block interface for USB storage dm: mmc: Add a legacy block interface for MMC dm: mmc: Add an implementation of the 'devnum' functions dm: scsi: Separate the non-command code into its own file dm: ide: Separate the non-command code into its own file dm: sata: Separate the non-command code into its own file dm: disk: Use legacy block driver info for block device access dm: usb: Drop the get_dev() function dm: ide: Drop the get_dev() function dm: mmc: Drop the get_dev() function dm: scsi: Drop the get_dev() function dm: sata: Drop the get_dev() function dm: systemace: Drop the get_dev() function dm: blk: Drop the systemace.h header dm: sandbox: Drop the host_get_dev() function dm: part: Drop the get_dev() method dm: ide: Add support for driver-model block devices dm: sandbox: Enable IDE dm: scsi: Add support for driver-model block devices dm: sandbox: Enable SCSI dm: sata: Add support for driver-model block devices dm: sandbox: Enable SATA dm: blk: Allow blk_create_device() to allocate the device number dm: blk: Add a easier way to create a named block device dm: systemace: Reorder function to avoid forward declarataions dm: systemace: Add driver-mode block-device support dm: sandbox: Enable systemace
README | 4 +- api/api_storage.c | 2 +- arch/arm/include/asm/arch-ls102xa/config.h | 2 +- arch/sandbox/include/asm/io.h | 15 + arch/x86/Kconfig | 3 + arch/x86/cpu/broadwell/sata.c | 2 +- arch/x86/cpu/intel_common/cpu.c | 2 +- arch/x86/cpu/ivybridge/bd82x6x.c | 2 +- arch/x86/cpu/ivybridge/sata.c | 2 +- board/cm5200/fwupdate.c | 2 +- board/mpl/pip405/README | 6 +- board/sandbox/MAINTAINERS | 7 + cmd/Makefile | 8 +- cmd/disk.c | 2 +- cmd/ide.c | 1352 +----------------------- cmd/mmc.c | 2 +- cmd/sata.c | 142 +-- cmd/scsi.c | 753 ++----------- cmd/usb.c | 16 +- common/Makefile | 6 + common/board_r.c | 4 +- common/ide.c | 1231 +++++++++++++++++++++ common/sata.c | 115 ++ common/scsi.c | 592 +++++++++++ common/spl/spl_sata.c | 2 +- common/spl/spl_usb.c | 2 +- common/usb_storage.c | 37 +- configs/sandbox_noblk_defconfig | 98 ++ disk/part.c | 22 +- drivers/Makefile | 1 + drivers/block/Kconfig | 5 +- drivers/block/Makefile | 8 +- drivers/block/{disk-uclass.c => ahci-uclass.c} | 6 +- drivers/block/blk-uclass.c | 324 ++++++ drivers/block/blk_legacy.c | 261 +++++ drivers/block/sandbox.c | 103 +- drivers/block/sandbox_scsi.c | 29 + drivers/block/sata_sandbox.c | 33 + drivers/block/sym53c8xx.c | 2 +- drivers/block/systemace.c | 110 +- drivers/mmc/mmc.c | 24 +- drivers/pci/pci.c | 4 - fs/fat/fat.c | 2 +- include/blk.h | 228 +++- include/config_cmd_all.h | 2 +- include/config_distro_bootcmd.h | 6 +- include/config_fallbacks.h | 2 +- include/configs/MPC8544DS.h | 2 +- include/configs/MPC8572DS.h | 2 +- include/configs/MPC8610HPCD.h | 2 +- include/configs/MPC8641HPCN.h | 4 +- include/configs/PIP405.h | 2 +- include/configs/am57xx_evm.h | 2 +- include/configs/cm_t54.h | 2 +- include/configs/db-88f6820-gp.h | 2 +- include/configs/dra7xx_evm.h | 2 +- include/configs/efi-x86.h | 2 +- include/configs/galileo.h | 2 +- include/configs/highbank.h | 2 +- include/configs/ls1043aqds.h | 2 +- include/configs/ls2080aqds.h | 2 +- include/configs/ls2080ardb.h | 2 +- include/configs/omap5_uevm.h | 2 +- include/configs/qemu-x86.h | 2 +- include/configs/sandbox.h | 23 + include/configs/sbc8641d.h | 2 - include/configs/sunxi-common.h | 2 +- include/configs/x86-common.h | 2 +- include/configs/xilinx_zynqmp.h | 2 +- include/dm/uclass-id.h | 2 +- include/ide.h | 8 + include/iotrace.h | 5 +- include/part.h | 15 - include/systemace.h | 17 - include/usb.h | 1 - 75 files changed, 3390 insertions(+), 2308 deletions(-) create mode 100644 common/ide.c create mode 100644 common/sata.c create mode 100644 common/scsi.c create mode 100644 configs/sandbox_noblk_defconfig rename drivers/block/{disk-uclass.c => ahci-uclass.c} (72%) create mode 100644 drivers/block/blk_legacy.c create mode 100644 drivers/block/sandbox_scsi.c create mode 100644 drivers/block/sata_sandbox.c delete mode 100644 include/systemace.h

Bring this support back so that sandbox can be compiled with CONFIG_BLK. This allows sandbox to have greater build coverage during the block-device transition. This can be removed again later.
This reverts commit 33cf727b1634dbd9cd68a6ebc444a88f053822d7.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/block/sandbox.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+)
diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c index 2d340ef..6d41508 100644 --- a/drivers/block/sandbox.c +++ b/drivers/block/sandbox.c @@ -17,6 +17,19 @@
DECLARE_GLOBAL_DATA_PTR;
+#ifndef CONFIG_BLK +static struct host_block_dev host_devices[CONFIG_HOST_MAX_DEVICES]; + +static struct host_block_dev *find_host_device(int dev) +{ + if (dev >= 0 && dev < CONFIG_HOST_MAX_DEVICES) + return &host_devices[dev]; + + return NULL; +} +#endif + +#ifdef CONFIG_BLK static unsigned long host_block_read(struct udevice *dev, unsigned long start, lbaint_t blkcnt, void *buffer) @@ -24,6 +37,18 @@ static unsigned long host_block_read(struct udevice *dev, struct host_block_dev *host_dev = dev_get_priv(dev); struct blk_desc *block_dev = dev_get_uclass_platdata(dev);
+#else +static unsigned long host_block_read(struct blk_desc *block_dev, + unsigned long start, lbaint_t blkcnt, + void *buffer) +{ + int dev = block_dev->devnum; + struct host_block_dev *host_dev = find_host_device(dev); + + if (!host_dev) + return -1; +#endif + if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) == -1) { printf("ERROR: Invalid block %lx\n", start); @@ -35,12 +60,21 @@ static unsigned long host_block_read(struct udevice *dev, return -1; }
+#ifdef CONFIG_BLK static unsigned long host_block_write(struct udevice *dev, unsigned long start, lbaint_t blkcnt, const void *buffer) { struct host_block_dev *host_dev = dev_get_priv(dev); struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#else +static unsigned long host_block_write(struct blk_desc *block_dev, + unsigned long start, lbaint_t blkcnt, + const void *buffer) +{ + int dev = block_dev->devnum; + struct host_block_dev *host_dev = find_host_device(dev); +#endif
if (os_lseek(host_dev->fd, start * block_dev->blksz, OS_SEEK_SET) == -1) { @@ -53,6 +87,7 @@ static unsigned long host_block_write(struct udevice *dev, return -1; }
+#ifdef CONFIG_BLK int host_dev_bind(int devnum, char *filename) { struct host_block_dev *host_dev; @@ -115,9 +150,51 @@ err: free(str); return ret; } +#else +int host_dev_bind(int dev, char *filename) +{ + struct host_block_dev *host_dev = find_host_device(dev); + + if (!host_dev) + return -1; + if (host_dev->blk_dev.priv) { + os_close(host_dev->fd); + host_dev->blk_dev.priv = NULL; + } + if (host_dev->filename) + free(host_dev->filename); + if (filename && *filename) { + host_dev->filename = strdup(filename); + } else { + host_dev->filename = NULL; + return 0; + } + + host_dev->fd = os_open(host_dev->filename, OS_O_RDWR); + if (host_dev->fd == -1) { + printf("Failed to access host backing file '%s'\n", + host_dev->filename); + return 1; + } + + struct blk_desc *blk_dev = &host_dev->blk_dev; + blk_dev->if_type = IF_TYPE_HOST; + blk_dev->priv = host_dev; + blk_dev->blksz = 512; + blk_dev->lba = os_lseek(host_dev->fd, 0, OS_SEEK_END) / blk_dev->blksz; + blk_dev->block_read = host_block_read; + blk_dev->block_write = host_block_write; + blk_dev->devnum = dev; + blk_dev->part_type = PART_TYPE_UNKNOWN; + part_init(blk_dev); + + return 0; +} +#endif
int host_get_dev_err(int devnum, struct blk_desc **blk_devp) { +#ifdef CONFIG_BLK struct udevice *dev; int ret;
@@ -125,6 +202,17 @@ int host_get_dev_err(int devnum, struct blk_desc **blk_devp) if (ret) return ret; *blk_devp = dev_get_uclass_platdata(dev); +#else + struct host_block_dev *host_dev = find_host_device(devnum); + + if (!host_dev) + return -ENODEV; + + if (!host_dev->blk_dev.priv) + return -ENOENT; + + *blk_devp = &host_dev->blk_dev; +#endif
return 0; } @@ -139,6 +227,7 @@ struct blk_desc *host_get_dev(int dev) return blk_dev; }
+#ifdef CONFIG_BLK static const struct blk_ops sandbox_host_blk_ops = { .read = host_block_read, .write = host_block_write, @@ -150,3 +239,4 @@ U_BOOT_DRIVER(sandbox_host_blk) = { .ops = &sandbox_host_blk_ops, .priv_auto_alloc_size = sizeof(struct host_block_dev), }; +#endif

On 1 May 2016 at 11:35, Simon Glass sjg@chromium.org wrote:
Bring this support back so that sandbox can be compiled with CONFIG_BLK. This allows sandbox to have greater build coverage during the block-device transition. This can be removed again later.
This reverts commit 33cf727b1634dbd9cd68a6ebc444a88f053822d7.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/sandbox.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+)
Applied to u-boot-dm.

While the driver-model block device support is in progress, it is useful to build sandbox both with and without CONFIG_BLK. Add a separate board for the latter.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
board/sandbox/MAINTAINERS | 7 +++ configs/sandbox_noblk_defconfig | 98 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 configs/sandbox_noblk_defconfig
diff --git a/board/sandbox/MAINTAINERS b/board/sandbox/MAINTAINERS index 10d88a2..f5db773 100644 --- a/board/sandbox/MAINTAINERS +++ b/board/sandbox/MAINTAINERS @@ -4,3 +4,10 @@ S: Maintained F: board/sandbox/ F: include/configs/sandbox.h F: configs/sandbox_defconfig + +SANDBOX_NOBLK BOARD +M: Simon Glass sjg@chromium.org +S: Maintained +F: board/sandbox/ +F: include/configs/sandbox.h +F: configs/sandbox_noblk_defconfig diff --git a/configs/sandbox_noblk_defconfig b/configs/sandbox_noblk_defconfig new file mode 100644 index 0000000..038dad6 --- /dev/null +++ b/configs/sandbox_noblk_defconfig @@ -0,0 +1,98 @@ +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_PCI=y +CONFIG_DEFAULT_DEVICE_TREE="sandbox" +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y +CONFIG_BOOTSTAGE=y +CONFIG_BOOTSTAGE_REPORT=y +CONFIG_CONSOLE_RECORD=y +CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000 +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_REMOTEPROC=y +CONFIG_CMD_GPIO=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_SOUND=y +CONFIG_CMD_PMIC=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_TPM=y +CONFIG_CMD_TPM_TEST=y +CONFIG_OF_CONTROL=y +CONFIG_OF_HOSTFILE=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +CONFIG_DEVRES=y +CONFIG_ADC=y +CONFIG_ADC_SANDBOX=y +CONFIG_CLK=y +CONFIG_SANDBOX_GPIO=y +CONFIG_PM8916_GPIO=y +CONFIG_SYS_I2C_SANDBOX=y +CONFIG_CROS_EC_KEYB=y +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_CMD_CROS_EC=y +CONFIG_CROS_EC=y +CONFIG_CROS_EC_SANDBOX=y +CONFIG_RESET=y +CONFIG_DM_MMC=y +CONFIG_SPI_FLASH_SANDBOX=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_ATMEL=y +CONFIG_SPI_FLASH_EON=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_SST=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_DM_ETH=y +CONFIG_DM_PCI=y +CONFIG_DM_PCI_COMPAT=y +CONFIG_PCI_SANDBOX=y +CONFIG_PINCTRL=y +CONFIG_PINCONF=y +CONFIG_PINCTRL_SANDBOX=y +CONFIG_DM_PMIC=y +CONFIG_DM_PMIC_SANDBOX=y +CONFIG_PMIC_PM8916=y +CONFIG_SPMI=y +CONFIG_SPMI_SANDBOX=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_SANDBOX=y +CONFIG_RAM=y +CONFIG_REMOTEPROC_SANDBOX=y +CONFIG_DM_RTC=y +CONFIG_SANDBOX_SERIAL=y +CONFIG_SOUND=y +CONFIG_SOUND_SANDBOX=y +CONFIG_SANDBOX_SPI=y +CONFIG_TIMER=y +CONFIG_TIMER_EARLY=y +CONFIG_SANDBOX_TIMER=y +CONFIG_TPM_TIS_SANDBOX=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_EMUL=y +CONFIG_USB_STORAGE=y +CONFIG_USB_KEYBOARD=y +CONFIG_SYS_USB_EVENT_POLL=y +CONFIG_DM_VIDEO=y +CONFIG_CONSOLE_ROTATION=y +CONFIG_CONSOLE_TRUETYPE=y +CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y +CONFIG_VIDEO_SANDBOX_SDL=y +CONFIG_CMD_DHRYSTONE=y +CONFIG_TPM=y +CONFIG_LZ4=y +CONFIG_ERRNO_STR=y +CONFIG_UNIT_TEST=y +CONFIG_UT_TIME=y +CONFIG_UT_DM=y +CONFIG_UT_ENV=y +CONFIG_MMC=y +CONFIG_SANDBOX_MMC=y

On 1 May 2016 at 11:35, Simon Glass sjg@chromium.org wrote:
While the driver-model block device support is in progress, it is useful to build sandbox both with and without CONFIG_BLK. Add a separate board for the latter.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
board/sandbox/MAINTAINERS | 7 +++ configs/sandbox_noblk_defconfig | 98 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 configs/sandbox_noblk_defconfig
Applied to u-boot-dm.

This option is not used by any board. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com ---
Changes in v2: None
drivers/pci/pci.c | 4 ---- include/configs/MPC8641HPCN.h | 2 -- include/configs/sbc8641d.h | 2 -- 3 files changed, 8 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 4619089..4b73a0f 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -175,11 +175,7 @@ pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) int bus;
for (hose = pci_get_hose_head(); hose; hose = hose->next) { -#ifdef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE - for (bus = hose->last_busno; bus >= hose->first_busno; bus--) { -#else for (bus = hose->first_busno; bus <= hose->last_busno; bus++) { -#endif bdf = pci_hose_find_devices(hose, bus, ids, &index); if (bdf != -1) return bdf; diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h index 3569849..4ba2163 100644 --- a/include/configs/MPC8641HPCN.h +++ b/include/configs/MPC8641HPCN.h @@ -354,8 +354,6 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
#define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */
-#undef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE - #define CONFIG_PCI_PNP /* do pci plug-and-play */
#undef CONFIG_EEPRO100 diff --git a/include/configs/sbc8641d.h b/include/configs/sbc8641d.h index f34cef5..b213d50 100644 --- a/include/configs/sbc8641d.h +++ b/include/configs/sbc8641d.h @@ -297,8 +297,6 @@
#define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */
-#undef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE - #define CONFIG_PCI_PNP /* do pci plug-and-play */
#undef CONFIG_EEPRO100

On 1 May 2016 at 11:35, Simon Glass sjg@chromium.org wrote:
This option is not used by any board. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org Reviewed-by: Bin Meng bmeng.cn@gmail.com
Changes in v2: None
drivers/pci/pci.c | 4 ---- include/configs/MPC8641HPCN.h | 2 -- include/configs/sbc8641d.h | 2 -- 3 files changed, 8 deletions(-)
Applied to u-boot-dm.

This started as 'ahci' and was renamed to 'disk' during code review. But it seems that this is too generic. Now that we have a 'blk' uclass, we can use that as the generic piece, and revert to ahci for this.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
arch/x86/Kconfig | 3 +++ arch/x86/cpu/broadwell/sata.c | 2 +- arch/x86/cpu/intel_common/cpu.c | 2 +- arch/x86/cpu/ivybridge/bd82x6x.c | 2 +- arch/x86/cpu/ivybridge/sata.c | 2 +- drivers/block/Kconfig | 5 ++--- drivers/block/Makefile | 2 +- drivers/block/{disk-uclass.c => ahci-uclass.c} | 6 +++--- include/dm/uclass-id.h | 2 +- 9 files changed, 14 insertions(+), 12 deletions(-) rename drivers/block/{disk-uclass.c => ahci-uclass.c} (72%)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 4ef27dc..396023e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -47,6 +47,9 @@ source "arch/x86/cpu/queensbay/Kconfig"
# architecture-specific options below
+config AHCI + default y + config SYS_MALLOC_F_LEN default 0x800
diff --git a/arch/x86/cpu/broadwell/sata.c b/arch/x86/cpu/broadwell/sata.c index dfb8486..2e47082 100644 --- a/arch/x86/cpu/broadwell/sata.c +++ b/arch/x86/cpu/broadwell/sata.c @@ -261,7 +261,7 @@ static const struct udevice_id broadwell_ahci_ids[] = {
U_BOOT_DRIVER(ahci_broadwell_drv) = { .name = "ahci_broadwell", - .id = UCLASS_DISK, + .id = UCLASS_AHCI, .of_match = broadwell_ahci_ids, .ofdata_to_platdata = broadwell_sata_ofdata_to_platdata, .probe = broadwell_sata_probe, diff --git a/arch/x86/cpu/intel_common/cpu.c b/arch/x86/cpu/intel_common/cpu.c index 93e4505..0fdef6f 100644 --- a/arch/x86/cpu/intel_common/cpu.c +++ b/arch/x86/cpu/intel_common/cpu.c @@ -58,7 +58,7 @@ int cpu_common_init(void) return -ENODEV;
/* Cause the SATA device to do its early init */ - uclass_first_device(UCLASS_DISK, &dev); + uclass_first_device(UCLASS_AHCI, &dev);
return 0; } diff --git a/arch/x86/cpu/ivybridge/bd82x6x.c b/arch/x86/cpu/ivybridge/bd82x6x.c index 4c039ac..5b58d6c 100644 --- a/arch/x86/cpu/ivybridge/bd82x6x.c +++ b/arch/x86/cpu/ivybridge/bd82x6x.c @@ -162,7 +162,7 @@ static int bd82x6x_probe(struct udevice *dev) return 0;
/* Cause the SATA device to do its init */ - uclass_first_device(UCLASS_DISK, &dev); + uclass_first_device(UCLASS_AHCI, &dev);
ret = syscon_get_by_driver_data(X86_SYSCON_GMA, &gma_dev); if (ret) diff --git a/arch/x86/cpu/ivybridge/sata.c b/arch/x86/cpu/ivybridge/sata.c index c3d1057..1ce8195 100644 --- a/arch/x86/cpu/ivybridge/sata.c +++ b/arch/x86/cpu/ivybridge/sata.c @@ -233,7 +233,7 @@ static const struct udevice_id bd82x6x_ahci_ids[] = {
U_BOOT_DRIVER(ahci_ivybridge_drv) = { .name = "ahci_ivybridge", - .id = UCLASS_DISK, + .id = UCLASS_AHCI, .of_match = bd82x6x_ahci_ids, .probe = bd82x6x_sata_probe, }; diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index fcc9ccd..80eea84 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -9,10 +9,9 @@ config BLK be partitioned into several areas, called 'partitions' in U-Boot. A filesystem can be placed in each partition.
-config DISK - bool "Support disk controllers with driver model" +config AHCI + bool "Support SATA controllers with driver model" depends on DM - default y if DM help This enables a uclass for disk controllers in U-Boot. Various driver types can use this, such as AHCI/SATA. It does not provide any standard diff --git a/drivers/block/Makefile b/drivers/block/Makefile index a43492f..b832ae1 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -7,7 +7,7 @@
obj-$(CONFIG_BLK) += blk-uclass.o
-obj-$(CONFIG_DISK) += disk-uclass.o +obj-$(CONFIG_AHCI) += ahci-uclass.o obj-$(CONFIG_SCSI_AHCI) += ahci.o obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o obj-$(CONFIG_FSL_SATA) += fsl_sata.o diff --git a/drivers/block/disk-uclass.c b/drivers/block/ahci-uclass.c similarity index 72% rename from drivers/block/disk-uclass.c rename to drivers/block/ahci-uclass.c index d665b35..7b8c326 100644 --- a/drivers/block/disk-uclass.c +++ b/drivers/block/ahci-uclass.c @@ -8,7 +8,7 @@ #include <common.h> #include <dm.h>
-UCLASS_DRIVER(disk) = { - .id = UCLASS_DISK, - .name = "disk", +UCLASS_DRIVER(ahci) = { + .id = UCLASS_AHCI, + .name = "ahci", }; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index cbf9b2c..a5cf6e2 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -26,11 +26,11 @@ enum uclass_id {
/* U-Boot uclasses start here - in alphabetical order */ UCLASS_ADC, /* Analog-to-digital converter */ + UCLASS_AHCI, /* SATA disk controller */ UCLASS_BLK, /* Block device */ UCLASS_CLK, /* Clock source, e.g. used by peripherals */ UCLASS_CPU, /* CPU, typically part of an SoC */ UCLASS_CROS_EC, /* Chrome OS EC */ - UCLASS_DISK, /* Disk controller, e.g. SATA */ UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */ UCLASS_DMA, /* Direct Memory Access */ UCLASS_RAM, /* RAM controller */

On 1 May 2016 at 11:35, Simon Glass sjg@chromium.org wrote:
This started as 'ahci' and was renamed to 'disk' during code review. But it seems that this is too generic. Now that we have a 'blk' uclass, we can use that as the generic piece, and revert to ahci for this.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
arch/x86/Kconfig | 3 +++ arch/x86/cpu/broadwell/sata.c | 2 +- arch/x86/cpu/intel_common/cpu.c | 2 +- arch/x86/cpu/ivybridge/bd82x6x.c | 2 +- arch/x86/cpu/ivybridge/sata.c | 2 +- drivers/block/Kconfig | 5 ++--- drivers/block/Makefile | 2 +- drivers/block/{disk-uclass.c => ahci-uclass.c} | 6 +++--- include/dm/uclass-id.h | 2 +- 9 files changed, 14 insertions(+), 12 deletions(-) rename drivers/block/{disk-uclass.c => ahci-uclass.c} (72%)
Applied to u-boot-dm.

If an address is used with readb() and writeb() which is smaller than the expected size (e.g. 32-bit value on a machine with 64-bit addresses), a warning results. Fix this by adding a cast.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Tweak the cast
include/iotrace.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/include/iotrace.h b/include/iotrace.h index 9bd1f16..e4ceb61 100644 --- a/include/iotrace.h +++ b/include/iotrace.h @@ -31,10 +31,11 @@ #define writew(val, addr) iotrace_writew(val, (const void *)(addr))
#undef readb -#define readb(addr) iotrace_readb((const void *)(addr)) +#define readb(addr) iotrace_readb((const void *)(uintptr_t)addr)
#undef writeb -#define writeb(val, addr) iotrace_writeb(val, (const void *)(addr)) +#define writeb(val, addr) \ + iotrace_writeb(val, (const void *)(uintptr_t)addr)
#endif

On 1 May 2016 at 11:35, Simon Glass sjg@chromium.org wrote:
If an address is used with readb() and writeb() which is smaller than the expected size (e.g. 32-bit value on a machine with 64-bit addresses), a warning results. Fix this by adding a cast.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Tweak the cast
include/iotrace.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
Applied to u-boot-dm.

Add outsw() and insw() functions for sandbox, as these are needed by the IDE code. The functions will not do anything useful if called, but allow the code to be compiled.
Also add out16() and in16(), required by systemace.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Make the string functions empty, since the implementation is not useful
arch/sandbox/include/asm/io.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h index b87ee19..6919632 100644 --- a/arch/sandbox/include/asm/io.h +++ b/arch/sandbox/include/asm/io.h @@ -56,6 +56,21 @@ void outl(unsigned int value, unsigned int addr); void outw(unsigned int value, unsigned int addr); void outb(unsigned int value, unsigned int addr);
+static inline void _insw(volatile u16 *port, void *buf, int ns) +{ +} + +static inline void _outsw(volatile u16 *port, const void *buf, int ns) +{ +} + +#define insw(port, buf, ns) _insw((u16 *)port, buf, ns) +#define outsw(port, buf, ns) _outsw((u16 *)port, buf, ns) + +/* For systemace.c */ +#define out16(addr, val) +#define in16(addr) 0 + #include <iotrace.h> #include <asm/types.h>

On 1 May 2016 at 11:35, Simon Glass sjg@chromium.org wrote:
Add outsw() and insw() functions for sandbox, as these are needed by the IDE code. The functions will not do anything useful if called, but allow the code to be compiled.
Also add out16() and in16(), required by systemace.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Make the string functions empty, since the implementation is not useful
arch/sandbox/include/asm/io.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
Applied to u-boot-dm.

Add some functions needed by the SCSI code. This allows it to be compiled for sandbox, thus increasing build coverage.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/block/Makefile | 2 +- drivers/block/sandbox_scsi.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 drivers/block/sandbox_scsi.c
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index b832ae1..3b48eac 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o obj-$(CONFIG_SATA_SIL) += sata_sil.o obj-$(CONFIG_IDE_SIL680) += sil680.o -obj-$(CONFIG_SANDBOX) += sandbox.o +obj-$(CONFIG_SANDBOX) += sandbox.o sandbox_scsi.o obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o obj-$(CONFIG_SYSTEMACE) += systemace.o obj-$(CONFIG_BLOCK_CACHE) += blkcache.o diff --git a/drivers/block/sandbox_scsi.c b/drivers/block/sandbox_scsi.c new file mode 100644 index 0000000..d342a7a --- /dev/null +++ b/drivers/block/sandbox_scsi.c @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2015 Google, Inc + * Written by Simon Glass sjg@chromium.org + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This file contains dummy implementations of SCSI functions requried so + * that CONFIG_SCSI_can be enabled for sandbox. + */ + +#include <common.h> +#include <scsi.h> + +void scsi_bus_reset(void) +{ +} + +void scsi_init(void) +{ +} + +int scsi_exec(ccb *pccb) +{ + return 0; +} + +void scsi_print_error(ccb *pccb) +{ +}

On Sun, May 01, 2016 at 11:35:55AM -0600, Simon Glass wrote:
Add some functions needed by the SCSI code. This allows it to be compiled for sandbox, thus increasing build coverage.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/Makefile | 2 +- drivers/block/sandbox_scsi.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 drivers/block/sandbox_scsi.c
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index b832ae1..3b48eac 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o obj-$(CONFIG_SATA_SIL) += sata_sil.o obj-$(CONFIG_IDE_SIL680) += sil680.o -obj-$(CONFIG_SANDBOX) += sandbox.o +obj-$(CONFIG_SANDBOX) += sandbox.o sandbox_scsi.o obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o obj-$(CONFIG_SYSTEMACE) += systemace.o obj-$(CONFIG_BLOCK_CACHE) += blkcache.o diff --git a/drivers/block/sandbox_scsi.c b/drivers/block/sandbox_scsi.c new file mode 100644 index 0000000..d342a7a --- /dev/null +++ b/drivers/block/sandbox_scsi.c @@ -0,0 +1,29 @@ +/*
- Copyright (C) 2015 Google, Inc
- Written by Simon Glass sjg@chromium.org
- SPDX-License-Identifier: GPL-2.0+
- This file contains dummy implementations of SCSI functions requried so
- that CONFIG_SCSI_can be enabled for sandbox.
Typo. And I assume long term we can delete this file as we should be able to eventually compile in the various SCSI controllers and have them be not probed and OK, yes (and similar for SATA)?

Hi Tom,
On 2 May 2016 at 19:02, Tom Rini trini@konsulko.com wrote:
On Sun, May 01, 2016 at 11:35:55AM -0600, Simon Glass wrote:
Add some functions needed by the SCSI code. This allows it to be compiled for sandbox, thus increasing build coverage.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/Makefile | 2 +- drivers/block/sandbox_scsi.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 drivers/block/sandbox_scsi.c
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index b832ae1..3b48eac 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o obj-$(CONFIG_SATA_SIL) += sata_sil.o obj-$(CONFIG_IDE_SIL680) += sil680.o -obj-$(CONFIG_SANDBOX) += sandbox.o +obj-$(CONFIG_SANDBOX) += sandbox.o sandbox_scsi.o obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o obj-$(CONFIG_SYSTEMACE) += systemace.o obj-$(CONFIG_BLOCK_CACHE) += blkcache.o diff --git a/drivers/block/sandbox_scsi.c b/drivers/block/sandbox_scsi.c new file mode 100644 index 0000000..d342a7a --- /dev/null +++ b/drivers/block/sandbox_scsi.c @@ -0,0 +1,29 @@ +/*
- Copyright (C) 2015 Google, Inc
- Written by Simon Glass sjg@chromium.org
- SPDX-License-Identifier: GPL-2.0+
- This file contains dummy implementations of SCSI functions requried so
- that CONFIG_SCSI_can be enabled for sandbox.
Typo. And I assume long term we can delete this file as we should be able to eventually compile in the various SCSI controllers and have them be not probed and OK, yes (and similar for SATA)?
Yes that's right. Once there is a proper set of SCSi operations we can use those instead of these functions.
Regards, Simon

On 2 May 2016 at 19:02, Tom Rini trini@konsulko.com wrote:
On Sun, May 01, 2016 at 11:35:55AM -0600, Simon Glass wrote:
Add some functions needed by the SCSI code. This allows it to be compiled for sandbox, thus increasing build coverage.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/Makefile | 2 +- drivers/block/sandbox_scsi.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 drivers/block/sandbox_scsi.c
Applied to u-boot-dm.

Add some functions needed by the SATA code. This allows it to be compiled for sandbox, thus increasing build coverage.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/block/Makefile | 2 +- drivers/block/sata_sandbox.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 drivers/block/sata_sandbox.c
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 3b48eac..3f75934 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -22,7 +22,7 @@ obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_SATA_SIL3114) += sata_sil3114.o obj-$(CONFIG_SATA_SIL) += sata_sil.o obj-$(CONFIG_IDE_SIL680) += sil680.o -obj-$(CONFIG_SANDBOX) += sandbox.o sandbox_scsi.o +obj-$(CONFIG_SANDBOX) += sandbox.o sandbox_scsi.o sata_sandbox.o obj-$(CONFIG_SCSI_SYM53C8XX) += sym53c8xx.o obj-$(CONFIG_SYSTEMACE) += systemace.o obj-$(CONFIG_BLOCK_CACHE) += blkcache.o diff --git a/drivers/block/sata_sandbox.c b/drivers/block/sata_sandbox.c new file mode 100644 index 0000000..bd967d2 --- /dev/null +++ b/drivers/block/sata_sandbox.c @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015 Google, Inc + * Written by Simon Glass sjg@chromium.org + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> + +int init_sata(int dev) +{ + return 0; +} + +int reset_sata(int dev) +{ + return 0; +} + +int scan_sata(int dev) +{ + return 0; +} + +ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer) +{ + return 0; +} + +ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer) +{ + return 0; +}

On 1 May 2016 at 11:35, Simon Glass sjg@chromium.org wrote:
Add some functions needed by the SATA code. This allows it to be compiled for sandbox, thus increasing build coverage.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/Makefile | 2 +- drivers/block/sata_sandbox.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 drivers/block/sata_sandbox.c
Applied to u-boot-dm.

Reorder the code to avoid needing forward declarations.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Drop the code inside '#if 0'
cmd/scsi.c | 764 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 371 insertions(+), 393 deletions(-)
diff --git a/cmd/scsi.c b/cmd/scsi.c index 8991125..9ba070f 100644 --- a/cmd/scsi.c +++ b/cmd/scsi.c @@ -50,130 +50,230 @@ static int scsi_curr_dev; /* current device */
static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
-/******************************************************************************** - * forward declerations of some Setup Routines +/**************************************************************************************** + * scsi_read */ -void scsi_setup_test_unit_ready(ccb * pccb); -void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks); -void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks); -void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks);
-static void scsi_setup_write_ext(ccb *pccb, lbaint_t start, - unsigned short blocks); -void scsi_setup_inquiry(ccb * pccb); -void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); +/* almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_READ_BLK 0xFFFF +#define SCSI_LBA48_READ 0xFFFFFFF
+#ifdef CONFIG_SYS_64BIT_LBA +void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) +{ + pccb->cmd[0] = SCSI_READ16; + pccb->cmd[1] = pccb->lun<<5; + pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; + pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; + pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; + pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; + pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; + pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; + pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; + pccb->cmd[9] = ((unsigned char) (start)) & 0xff; + pccb->cmd[10] = 0; + pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; + pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; + pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; + pccb->cmd[14] = (unsigned char) blocks & 0xff; + pccb->cmd[15] = 0; + pccb->cmdlen = 16; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug ("scsi_setup_read16: cmd: %02X %02X " + "startblk %02X%02X%02X%02X%02X%02X%02X%02X " + "blccnt %02X%02X%02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], + pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); +} +#endif
-static int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, - unsigned long *blksz); -static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer); -static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer); +void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0]=SCSI_READ10; + pccb->cmd[1]=pccb->lun<<5; + pccb->cmd[2]=((unsigned char) (start>>24))&0xff; + pccb->cmd[3]=((unsigned char) (start>>16))&0xff; + pccb->cmd[4]=((unsigned char) (start>>8))&0xff; + pccb->cmd[5]=((unsigned char) (start))&0xff; + pccb->cmd[6]=0; + pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; + pccb->cmd[8]=(unsigned char) blocks & 0xff; + pccb->cmd[6]=0; + pccb->cmdlen=10; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", + pccb->cmd[0],pccb->cmd[1], + pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5], + pccb->cmd[7],pccb->cmd[8]); +}
+void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0] = SCSI_WRITE10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; + pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; + pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; + pccb->cmd[5] = ((unsigned char) (start)) & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[9] = 0; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + 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]); +}
-/********************************************************************************* - * (re)-scan the scsi bus and reports scsi device info - * to the user if mode = 1 - */ -void scsi_scan(int mode) +void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) { - unsigned char i,perq,modi,lun; - lbaint_t capacity; - unsigned long blksz; - ccb* pccb=(ccb *)&tempccb; + pccb->cmd[0]=SCSI_READ6; + pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); + pccb->cmd[2]=((unsigned char) (start>>8))&0xff; + pccb->cmd[3]=((unsigned char) (start))&0xff; + pccb->cmd[4]=(unsigned char) blocks & 0xff; + pccb->cmd[5]=0; + pccb->cmdlen=6; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", + pccb->cmd[0],pccb->cmd[1], + pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]); +}
- if(mode==1) { - printf("scanning bus for devices...\n"); - } - for(i=0;i<CONFIG_SYS_SCSI_MAX_DEVICE;i++) { - scsi_dev_desc[i].target=0xff; - scsi_dev_desc[i].lun=0xff; - scsi_dev_desc[i].lba=0; - scsi_dev_desc[i].blksz=0; - scsi_dev_desc[i].log2blksz = - LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); - scsi_dev_desc[i].type=DEV_TYPE_UNKNOWN; - scsi_dev_desc[i].vendor[0]=0; - scsi_dev_desc[i].product[0]=0; - scsi_dev_desc[i].revision[0]=0; - scsi_dev_desc[i].removable = false; - scsi_dev_desc[i].if_type=IF_TYPE_SCSI; - scsi_dev_desc[i].devnum = i; - scsi_dev_desc[i].part_type=PART_TYPE_UNKNOWN; - scsi_dev_desc[i].block_read=scsi_read; - scsi_dev_desc[i].block_write = scsi_write; - } - scsi_max_devs=0; - for(i=0;i<CONFIG_SYS_SCSI_MAX_SCSI_ID;i++) { - pccb->target=i; - for(lun=0;lun<CONFIG_SYS_SCSI_MAX_LUN;lun++) { - pccb->lun=lun; - pccb->pdata=(unsigned char *)&tempbuff; - pccb->datalen=512; - scsi_setup_inquiry(pccb); - if (scsi_exec(pccb) != true) { - if(pccb->contr_stat==SCSI_SEL_TIME_OUT) { - debug ("Selection timeout ID %d\n",pccb->target); - continue; /* selection timeout => assuming no device present */ - } - scsi_print_error(pccb); - continue; - } - perq=tempbuff[0]; - modi=tempbuff[1]; - if((perq & 0x1f)==0x1f) { - continue; /* skip unknown devices */ - } - if((modi&0x80)==0x80) /* drive is removable */ - scsi_dev_desc[scsi_max_devs].removable=true; - /* get info for this device */ - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], - &tempbuff[8], 8); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].product[0], - &tempbuff[16], 16); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0], - &tempbuff[32], 4); - scsi_dev_desc[scsi_max_devs].target=pccb->target; - scsi_dev_desc[scsi_max_devs].lun=pccb->lun;
- pccb->datalen=0; - scsi_setup_test_unit_ready(pccb); - if (scsi_exec(pccb) != true) { - if (scsi_dev_desc[scsi_max_devs].removable == true) { - scsi_dev_desc[scsi_max_devs].type=perq; - goto removable; - } - scsi_print_error(pccb); - continue; - } - if (scsi_read_capacity(pccb, &capacity, &blksz)) { - scsi_print_error(pccb); - continue; - } - scsi_dev_desc[scsi_max_devs].lba=capacity; - scsi_dev_desc[scsi_max_devs].blksz=blksz; - scsi_dev_desc[scsi_max_devs].log2blksz = - LOG2(scsi_dev_desc[scsi_max_devs].blksz); - scsi_dev_desc[scsi_max_devs].type=perq; - part_init(&scsi_dev_desc[scsi_max_devs]); -removable: - if(mode==1) { - printf (" Device %d: ", scsi_max_devs); - dev_print(&scsi_dev_desc[scsi_max_devs]); - } /* if mode */ - scsi_max_devs++; - } /* next LUN */ - } - if(scsi_max_devs>0) - scsi_curr_dev=0; +void scsi_setup_inquiry(ccb * pccb) +{ + pccb->cmd[0]=SCSI_INQUIRY; + pccb->cmd[1]=pccb->lun<<5; + pccb->cmd[2]=0; + pccb->cmd[3]=0; + if(pccb->datalen>255) + pccb->cmd[4]=255; else - scsi_curr_dev = -1; + pccb->cmd[4]=(unsigned char)pccb->datalen; + pccb->cmd[5]=0; + pccb->cmdlen=6; + pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ +}
- printf("Found %d device(s).\n", scsi_max_devs); -#ifndef CONFIG_SPL_BUILD - setenv_ulong("scsidevs", scsi_max_devs); +static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, void *buffer) +{ + int device = block_dev->devnum; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks = 0; + ccb* pccb=(ccb *)&tempccb; + device&=0xff; + /* Setup device + */ + pccb->target=scsi_dev_desc[device].target; + pccb->lun=scsi_dev_desc[device].lun; + buf_addr=(unsigned long)buffer; + start=blknr; + blks=blkcnt; + debug("\nscsi_read: dev %d startblk " LBAF + ", blccnt " LBAF " buffer %lx\n", + device, start, blks, (unsigned long)buffer); + do { + pccb->pdata=(unsigned char *)buf_addr; +#ifdef CONFIG_SYS_64BIT_LBA + if (start > SCSI_LBA48_READ) { + unsigned long blocks; + blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); + pccb->datalen = scsi_dev_desc[device].blksz * blocks; + scsi_setup_read16(pccb, start, blocks); + start += blocks; + blks -= blocks; + } else #endif + if (blks > SCSI_MAX_READ_BLK) { + pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; + smallblks=SCSI_MAX_READ_BLK; + scsi_setup_read_ext(pccb,start,smallblks); + start+=SCSI_MAX_READ_BLK; + blks-=SCSI_MAX_READ_BLK; + } + else { + pccb->datalen=scsi_dev_desc[device].blksz * blks; + smallblks=(unsigned short) blks; + scsi_setup_read_ext(pccb,start,smallblks); + start+=blks; + blks=0; + } + debug("scsi_read_ext: startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", + start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt-=blks; + break; + } + buf_addr+=pccb->datalen; + } while(blks!=0); + debug("scsi_read_ext: end startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); + return(blkcnt); +} + +/******************************************************************************* + * scsi_write + */ + +/* Almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_WRITE_BLK 0xFFFF + +static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer) +{ + int device = block_dev->devnum; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks; + ccb* pccb = (ccb *)&tempccb; + device &= 0xff; + /* Setup device + */ + pccb->target = scsi_dev_desc[device].target; + pccb->lun = scsi_dev_desc[device].lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; + debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + __func__, device, start, blks, (unsigned long)buffer); + do { + pccb->pdata = (unsigned char *)buf_addr; + if (blks > SCSI_MAX_WRITE_BLK) { + pccb->datalen = (scsi_dev_desc[device].blksz * + SCSI_MAX_WRITE_BLK); + smallblks = SCSI_MAX_WRITE_BLK; + scsi_setup_write_ext(pccb, start, smallblks); + start += SCSI_MAX_WRITE_BLK; + blks -= SCSI_MAX_WRITE_BLK; + } else { + pccb->datalen = scsi_dev_desc[device].blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_write_ext(pccb, start, smallblks); + start += blks; + blks = 0; + } + debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt -= blks; + break; + } + buf_addr += pccb->datalen; + } while (blks != 0); + debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + return blkcnt; }
int scsi_get_disk_count(void) @@ -327,192 +427,69 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("... is now current device\n"); return 0; } - if (strncmp(argv[1],"part",4) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) { - part_print(&scsi_dev_desc[dev]); - } - else { - printf ("\nSCSI device %d not available\n", dev); - } - return 1; - } - return CMD_RET_USAGE; - default: - /* at least 4 args */ - if (strcmp(argv[1],"read") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong blk = simple_strtoul(argv[3], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; - printf ("\nSCSI read: device %d block # %ld, count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_read(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR"); - return 0; - } else if (strcmp(argv[1], "write") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong blk = simple_strtoul(argv[3], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; - printf("\nSCSI write: device %d block # %ld, " - "count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_write(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf("%ld blocks written: %s\n", n, - (n == cnt) ? "OK" : "ERROR"); - return 0; - } - } /* switch */ - return CMD_RET_USAGE; -} - -U_BOOT_CMD( - scsi, 5, 1, do_scsi, - "SCSI sub-system", - "reset - reset SCSI controller\n" - "scsi info - show available SCSI devices\n" - "scsi scan - (re-)scan SCSI bus\n" - "scsi device [dev] - show or set current device\n" - "scsi part [dev] - print partition table of one or all SCSI devices\n" - "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'" -); - -U_BOOT_CMD( - scsiboot, 3, 1, do_scsiboot, - "boot from SCSI device", - "loadAddr dev:part" -); -#endif - -/**************************************************************************************** - * scsi_read - */ - -/* almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_READ_BLK 0xFFFF -#define SCSI_LBA48_READ 0xFFFFFFF - -static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks = 0; - ccb* pccb=(ccb *)&tempccb; - device&=0xff; - /* Setup device - */ - pccb->target=scsi_dev_desc[device].target; - pccb->lun=scsi_dev_desc[device].lun; - buf_addr=(unsigned long)buffer; - start=blknr; - blks=blkcnt; - debug("\nscsi_read: dev %d startblk " LBAF - ", blccnt " LBAF " buffer %lx\n", - device, start, blks, (unsigned long)buffer); - do { - pccb->pdata=(unsigned char *)buf_addr; -#ifdef CONFIG_SYS_64BIT_LBA - if (start > SCSI_LBA48_READ) { - unsigned long blocks; - blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); - pccb->datalen = scsi_dev_desc[device].blksz * blocks; - scsi_setup_read16(pccb, start, blocks); - start += blocks; - blks -= blocks; - } else -#endif - if (blks > SCSI_MAX_READ_BLK) { - pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; - smallblks=SCSI_MAX_READ_BLK; - scsi_setup_read_ext(pccb,start,smallblks); - start+=SCSI_MAX_READ_BLK; - blks-=SCSI_MAX_READ_BLK; - } - else { - pccb->datalen=scsi_dev_desc[device].blksz * blks; - smallblks=(unsigned short) blks; - scsi_setup_read_ext(pccb,start,smallblks); - start+=blks; - blks=0; - } - debug("scsi_read_ext: startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", - start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt-=blks; - break; - } - buf_addr+=pccb->datalen; - } while(blks!=0); - debug("scsi_read_ext: end startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); - return(blkcnt); -} - -/******************************************************************************* - * scsi_write - */ - -/* Almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_WRITE_BLK 0xFFFF - -static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks; - ccb* pccb = (ccb *)&tempccb; - device &= 0xff; - /* Setup device - */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; - buf_addr = (unsigned long)buffer; - start = blknr; - blks = blkcnt; - debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", - __func__, device, start, blks, (unsigned long)buffer); - do { - pccb->pdata = (unsigned char *)buf_addr; - if (blks > SCSI_MAX_WRITE_BLK) { - pccb->datalen = (scsi_dev_desc[device].blksz * - SCSI_MAX_WRITE_BLK); - smallblks = SCSI_MAX_WRITE_BLK; - scsi_setup_write_ext(pccb, start, smallblks); - start += SCSI_MAX_WRITE_BLK; - blks -= SCSI_MAX_WRITE_BLK; - } else { - pccb->datalen = scsi_dev_desc[device].blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_write_ext(pccb, start, smallblks); - start += blks; - blks = 0; - } - debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt -= blks; - break; - } - buf_addr += pccb->datalen; - } while (blks != 0); - debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - return blkcnt; + if (strncmp(argv[1],"part",4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) { + part_print(&scsi_dev_desc[dev]); + } + else { + printf ("\nSCSI device %d not available\n", dev); + } + return 1; + } + return CMD_RET_USAGE; + default: + /* at least 4 args */ + if (strcmp(argv[1],"read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong blk = simple_strtoul(argv[3], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + printf ("\nSCSI read: device %d block # %ld, count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_read(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR"); + return 0; + } else if (strcmp(argv[1], "write") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong blk = simple_strtoul(argv[3], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + printf("\nSCSI write: device %d block # %ld, " + "count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_write(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf("%ld blocks written: %s\n", n, + (n == cnt) ? "OK" : "ERROR"); + return 0; + } + } /* switch */ + return CMD_RET_USAGE; }
+U_BOOT_CMD( + scsi, 5, 1, do_scsi, + "SCSI sub-system", + "reset - reset SCSI controller\n" + "scsi info - show available SCSI devices\n" + "scsi scan - (re-)scan SCSI bus\n" + "scsi device [dev] - show or set current device\n" + "scsi part [dev] - print partition table of one or all SCSI devices\n" + "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'" +); + +U_BOOT_CMD( + scsiboot, 3, 1, do_scsiboot, + "boot from SCSI device", + "loadAddr dev:part" +); +#endif + /* copy src to dest, skipping leading and trailing blanks * and null terminate the string */ @@ -630,105 +607,106 @@ void scsi_setup_test_unit_ready(ccb * pccb) pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ }
-#ifdef CONFIG_SYS_64BIT_LBA -void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) -{ - pccb->cmd[0] = SCSI_READ16; - pccb->cmd[1] = pccb->lun<<5; - pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; - pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; - pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; - pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; - pccb->cmd[9] = ((unsigned char) (start)) & 0xff; - pccb->cmd[10] = 0; - pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; - pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; - pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; - pccb->cmd[14] = (unsigned char) blocks & 0xff; - pccb->cmd[15] = 0; - pccb->cmdlen = 16; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read16: cmd: %02X %02X " - "startblk %02X%02X%02X%02X%02X%02X%02X%02X " - "blccnt %02X%02X%02X%02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], - pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); -} -#endif - -void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0]=SCSI_READ10; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=((unsigned char) (start>>24))&0xff; - pccb->cmd[3]=((unsigned char) (start>>16))&0xff; - pccb->cmd[4]=((unsigned char) (start>>8))&0xff; - pccb->cmd[5]=((unsigned char) (start))&0xff; - pccb->cmd[6]=0; - pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; - pccb->cmd[8]=(unsigned char) blocks & 0xff; - pccb->cmd[6]=0; - pccb->cmdlen=10; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", - pccb->cmd[0],pccb->cmd[1], - pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5], - pccb->cmd[7],pccb->cmd[8]); -} - -void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_WRITE10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start)) & 0xff; - pccb->cmd[6] = 0; - pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; - pccb->cmd[8] = (unsigned char)blocks & 0xff; - pccb->cmd[9] = 0; - pccb->cmdlen = 10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - 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]); -} - -void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) +/********************************************************************************* + * (re)-scan the scsi bus and reports scsi device info + * to the user if mode = 1 + */ +void scsi_scan(int mode) { - pccb->cmd[0]=SCSI_READ6; - pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); - pccb->cmd[2]=((unsigned char) (start>>8))&0xff; - pccb->cmd[3]=((unsigned char) (start))&0xff; - pccb->cmd[4]=(unsigned char) blocks & 0xff; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", - pccb->cmd[0],pccb->cmd[1], - pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]); -} + unsigned char i,perq,modi,lun; + lbaint_t capacity; + unsigned long blksz; + ccb* pccb=(ccb *)&tempccb;
+ if(mode==1) { + printf("scanning bus for devices...\n"); + } + for(i=0;i<CONFIG_SYS_SCSI_MAX_DEVICE;i++) { + scsi_dev_desc[i].target=0xff; + scsi_dev_desc[i].lun=0xff; + scsi_dev_desc[i].lba=0; + scsi_dev_desc[i].blksz=0; + scsi_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); + scsi_dev_desc[i].type=DEV_TYPE_UNKNOWN; + scsi_dev_desc[i].vendor[0]=0; + scsi_dev_desc[i].product[0]=0; + scsi_dev_desc[i].revision[0]=0; + scsi_dev_desc[i].removable = false; + scsi_dev_desc[i].if_type=IF_TYPE_SCSI; + scsi_dev_desc[i].devnum = i; + scsi_dev_desc[i].part_type=PART_TYPE_UNKNOWN; + scsi_dev_desc[i].block_read=scsi_read; + scsi_dev_desc[i].block_write = scsi_write; + } + scsi_max_devs=0; + for(i=0;i<CONFIG_SYS_SCSI_MAX_SCSI_ID;i++) { + pccb->target=i; + for(lun=0;lun<CONFIG_SYS_SCSI_MAX_LUN;lun++) { + pccb->lun=lun; + pccb->pdata=(unsigned char *)&tempbuff; + pccb->datalen=512; + scsi_setup_inquiry(pccb); + if (scsi_exec(pccb) != true) { + if(pccb->contr_stat==SCSI_SEL_TIME_OUT) { + debug ("Selection timeout ID %d\n",pccb->target); + continue; /* selection timeout => assuming no device present */ + } + scsi_print_error(pccb); + continue; + } + perq=tempbuff[0]; + modi=tempbuff[1]; + if((perq & 0x1f)==0x1f) { + continue; /* skip unknown devices */ + } + if((modi&0x80)==0x80) /* drive is removable */ + scsi_dev_desc[scsi_max_devs].removable=true; + /* get info for this device */ + scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], + &tempbuff[8], 8); + scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].product[0], + &tempbuff[16], 16); + scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0], + &tempbuff[32], 4); + scsi_dev_desc[scsi_max_devs].target=pccb->target; + scsi_dev_desc[scsi_max_devs].lun=pccb->lun;
-void scsi_setup_inquiry(ccb * pccb) -{ - pccb->cmd[0]=SCSI_INQUIRY; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - if(pccb->datalen>255) - pccb->cmd[4]=255; + pccb->datalen=0; + scsi_setup_test_unit_ready(pccb); + if (scsi_exec(pccb) != true) { + if (scsi_dev_desc[scsi_max_devs].removable == true) { + scsi_dev_desc[scsi_max_devs].type=perq; + goto removable; + } + scsi_print_error(pccb); + continue; + } + if (scsi_read_capacity(pccb, &capacity, &blksz)) { + scsi_print_error(pccb); + continue; + } + scsi_dev_desc[scsi_max_devs].lba=capacity; + scsi_dev_desc[scsi_max_devs].blksz=blksz; + scsi_dev_desc[scsi_max_devs].log2blksz = + LOG2(scsi_dev_desc[scsi_max_devs].blksz); + scsi_dev_desc[scsi_max_devs].type=perq; + part_init(&scsi_dev_desc[scsi_max_devs]); +removable: + if(mode==1) { + printf (" Device %d: ", scsi_max_devs); + dev_print(&scsi_dev_desc[scsi_max_devs]); + } /* if mode */ + scsi_max_devs++; + } /* next LUN */ + } + if(scsi_max_devs>0) + scsi_curr_dev=0; else - pccb->cmd[4]=(unsigned char)pccb->datalen; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + scsi_curr_dev = -1; + + printf("Found %d device(s).\n", scsi_max_devs); +#ifndef CONFIG_SPL_BUILD + setenv_ulong("scsidevs", scsi_max_devs); +#endif }

On 1 May 2016 at 11:35, Simon Glass sjg@chromium.org wrote:
Reorder the code to avoid needing forward declarations.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Drop the code inside '#if 0'
cmd/scsi.c | 764 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 371 insertions(+), 393 deletions(-)
Applied to u-boot-dm.

Update the code style of this file so that it passes checkpatch.pl.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
cmd/scsi.c | 459 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 226 insertions(+), 233 deletions(-)
diff --git a/cmd/scsi.c b/cmd/scsi.c index 9ba070f..751fc58 100644 --- a/cmd/scsi.c +++ b/cmd/scsi.c @@ -50,59 +50,53 @@ static int scsi_curr_dev; /* current device */
static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE];
-/**************************************************************************************** - * scsi_read - */ - /* almost the maximum amount of the scsi_ext command.. */ #define SCSI_MAX_READ_BLK 0xFFFF #define SCSI_LBA48_READ 0xFFFFFFF
#ifdef CONFIG_SYS_64BIT_LBA -void scsi_setup_read16(ccb * pccb, lbaint_t start, unsigned long blocks) +void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks) { pccb->cmd[0] = SCSI_READ16; - pccb->cmd[1] = pccb->lun<<5; - pccb->cmd[2] = ((unsigned char) (start >> 56)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start >> 48)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start >> 40)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start >> 32)) & 0xff; - pccb->cmd[6] = ((unsigned char) (start >> 24)) & 0xff; - pccb->cmd[7] = ((unsigned char) (start >> 16)) & 0xff; - pccb->cmd[8] = ((unsigned char) (start >> 8)) & 0xff; - pccb->cmd[9] = ((unsigned char) (start)) & 0xff; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff; + pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff; + pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[9] = (unsigned char)start & 0xff; pccb->cmd[10] = 0; - pccb->cmd[11] = ((unsigned char) (blocks >> 24)) & 0xff; - pccb->cmd[12] = ((unsigned char) (blocks >> 16)) & 0xff; - pccb->cmd[13] = ((unsigned char) (blocks >> 8)) & 0xff; - pccb->cmd[14] = (unsigned char) blocks & 0xff; + pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff; + pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff; + pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[14] = (unsigned char)blocks & 0xff; pccb->cmd[15] = 0; pccb->cmdlen = 16; pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read16: cmd: %02X %02X " - "startblk %02X%02X%02X%02X%02X%02X%02X%02X " - "blccnt %02X%02X%02X%02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], - pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); + debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], + pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); } #endif
void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) { - pccb->cmd[0]=SCSI_READ10; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=((unsigned char) (start>>24))&0xff; - pccb->cmd[3]=((unsigned char) (start>>16))&0xff; - pccb->cmd[4]=((unsigned char) (start>>8))&0xff; - pccb->cmd[5]=((unsigned char) (start))&0xff; - pccb->cmd[6]=0; - pccb->cmd[7]=((unsigned char) (blocks>>8))&0xff; - pccb->cmd[8]=(unsigned char) blocks & 0xff; - pccb->cmd[6]=0; + pccb->cmd[0] = SCSI_READ10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[6] = 0; pccb->cmdlen=10; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", pccb->cmd[0],pccb->cmd[1], pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5], @@ -113,12 +107,12 @@ void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) { pccb->cmd[0] = SCSI_WRITE10; pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = ((unsigned char) (start>>24)) & 0xff; - pccb->cmd[3] = ((unsigned char) (start>>16)) & 0xff; - pccb->cmd[4] = ((unsigned char) (start>>8)) & 0xff; - pccb->cmd[5] = ((unsigned char) (start)) & 0xff; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; pccb->cmd[6] = 0; - pccb->cmd[7] = ((unsigned char) (blocks>>8)) & 0xff; + pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff; pccb->cmd[8] = (unsigned char)blocks & 0xff; pccb->cmd[9] = 0; pccb->cmdlen = 10; @@ -132,33 +126,33 @@ void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks)
void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) { - pccb->cmd[0]=SCSI_READ6; - pccb->cmd[1]=pccb->lun<<5 | (((unsigned char)(start>>16))&0x1f); - pccb->cmd[2]=((unsigned char) (start>>8))&0xff; - pccb->cmd[3]=((unsigned char) (start))&0xff; - pccb->cmd[4]=(unsigned char) blocks & 0xff; - pccb->cmd[5]=0; + pccb->cmd[0] = SCSI_READ6; + pccb->cmd[1] = pccb->lun << 5 | ((unsigned char)(start >> 16) & 0x1f); + pccb->cmd[2] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[3] = (unsigned char)start & 0xff; + pccb->cmd[4] = (unsigned char)blocks & 0xff; + pccb->cmd[5] = 0; pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", - pccb->cmd[0],pccb->cmd[1], - pccb->cmd[2],pccb->cmd[3],pccb->cmd[4]); + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4]); }
void scsi_setup_inquiry(ccb * pccb) { - pccb->cmd[0]=SCSI_INQUIRY; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - if(pccb->datalen>255) - pccb->cmd[4]=255; + pccb->cmd[0] = SCSI_INQUIRY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + if (pccb->datalen > 255) + pccb->cmd[4] = 255; else - pccb->cmd[4]=(unsigned char)pccb->datalen; - pccb->cmd[5]=0; + pccb->cmd[4] = (unsigned char)pccb->datalen; + pccb->cmd[5] = 0; pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ }
static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, @@ -170,18 +164,18 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, unsigned short smallblks = 0; ccb* pccb=(ccb *)&tempccb; device&=0xff; - /* Setup device - */ - pccb->target=scsi_dev_desc[device].target; - pccb->lun=scsi_dev_desc[device].lun; - buf_addr=(unsigned long)buffer; - start=blknr; - blks=blkcnt; + + /* Setup device */ + pccb->target = scsi_dev_desc[device].target; + pccb->lun = scsi_dev_desc[device].lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; debug("\nscsi_read: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", device, start, blks, (unsigned long)buffer); do { - pccb->pdata=(unsigned char *)buf_addr; + pccb->pdata = (unsigned char *)buf_addr; #ifdef CONFIG_SYS_64BIT_LBA if (start > SCSI_LBA48_READ) { unsigned long blocks; @@ -193,17 +187,18 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, } else #endif if (blks > SCSI_MAX_READ_BLK) { - pccb->datalen=scsi_dev_desc[device].blksz * SCSI_MAX_READ_BLK; - smallblks=SCSI_MAX_READ_BLK; - scsi_setup_read_ext(pccb,start,smallblks); - start+=SCSI_MAX_READ_BLK; - blks-=SCSI_MAX_READ_BLK; + pccb->datalen = scsi_dev_desc[device].blksz * + SCSI_MAX_READ_BLK; + smallblks = SCSI_MAX_READ_BLK; + scsi_setup_read_ext(pccb, start, smallblks); + start += SCSI_MAX_READ_BLK; + blks -= SCSI_MAX_READ_BLK; } else { - pccb->datalen=scsi_dev_desc[device].blksz * blks; - smallblks=(unsigned short) blks; - scsi_setup_read_ext(pccb,start,smallblks); - start+=blks; + pccb->datalen = scsi_dev_desc[device].blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_read_ext(pccb, start, smallblks); + start += blks; blks=0; } debug("scsi_read_ext: startblk " LBAF @@ -211,14 +206,14 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, start, smallblks, buf_addr); if (scsi_exec(pccb) != true) { scsi_print_error(pccb); - blkcnt-=blks; + blkcnt -= blks; break; } buf_addr+=pccb->datalen; - } while(blks!=0); + } while (blks != 0); debug("scsi_read_ext: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); - return(blkcnt); + return blkcnt; }
/******************************************************************************* @@ -365,106 +360,106 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_USAGE;
case 2: - if (strncmp(argv[1],"res",3) == 0) { - printf("\nReset SCSI\n"); - scsi_bus_reset(); - scsi_scan(1); - return 0; - } - if (strncmp(argv[1],"inf",3) == 0) { - int i; - for (i=0; i<CONFIG_SYS_SCSI_MAX_DEVICE; ++i) { - if(scsi_dev_desc[i].type==DEV_TYPE_UNKNOWN) - continue; /* list only known devices */ - printf ("SCSI dev. %d: ", i); - dev_print(&scsi_dev_desc[i]); - } - return 0; - } - if (strncmp(argv[1],"dev",3) == 0) { - if ((scsi_curr_dev < 0) || (scsi_curr_dev >= CONFIG_SYS_SCSI_MAX_DEVICE)) { - printf("\nno SCSI devices available\n"); - return 1; - } - printf ("\n Device %d: ", scsi_curr_dev); - dev_print(&scsi_dev_desc[scsi_curr_dev]); - return 0; - } - if (strncmp(argv[1],"scan",4) == 0) { - scsi_scan(1); - return 0; + if (strncmp(argv[1], "res", 3) == 0) { + printf("\nReset SCSI\n"); + scsi_bus_reset(); + scsi_scan(1); + return 0; + } + if (strncmp(argv[1], "inf", 3) == 0) { + int i; + for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; ++i) { + if (scsi_dev_desc[i].type == DEV_TYPE_UNKNOWN) + continue; /* list only known devices */ + printf("SCSI dev. %d: ", i); + dev_print(&scsi_dev_desc[i]); } - if (strncmp(argv[1],"part",4) == 0) { - int dev, ok; - for (ok=0, dev=0; dev<CONFIG_SYS_SCSI_MAX_DEVICE; ++dev) { - if (scsi_dev_desc[dev].type!=DEV_TYPE_UNKNOWN) { - ok++; - if (dev) - printf("\n"); - debug ("print_part of %x\n",dev); - part_print(&scsi_dev_desc[dev]); - } - } - if (!ok) - printf("\nno SCSI devices available\n"); + return 0; + } + if (strncmp(argv[1], "dev", 3) == 0) { + if (scsi_curr_dev < 0 || + scsi_curr_dev >= CONFIG_SYS_SCSI_MAX_DEVICE) { + printf("\nno SCSI devices available\n"); return 1; } - return CMD_RET_USAGE; - case 3: - if (strncmp(argv[1],"dev",3) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - printf ("\nSCSI device %d: ", dev); - if (dev >= CONFIG_SYS_SCSI_MAX_DEVICE) { - printf("unknown device\n"); - return 1; - } - printf ("\n Device %d: ", dev); - dev_print(&scsi_dev_desc[dev]); - if(scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { - return 1; - } - scsi_curr_dev = dev; - printf("... is now current device\n"); - return 0; - } - if (strncmp(argv[1],"part",4) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); - if(scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) { + printf("\n Device %d: ", scsi_curr_dev); + dev_print(&scsi_dev_desc[scsi_curr_dev]); + return 0; + } + if (strncmp(argv[1], "scan", 4) == 0) { + scsi_scan(1); + return 0; + } + if (strncmp(argv[1], "part", 4) == 0) { + int dev, ok; + for (ok = 0, dev = 0; + dev < CONFIG_SYS_SCSI_MAX_DEVICE; ++dev) { + if (scsi_dev_desc[dev].type != + DEV_TYPE_UNKNOWN) { + ok++; + if (dev) + printf("\n"); + debug("print_part of %x\n", dev); part_print(&scsi_dev_desc[dev]); } - else { - printf ("\nSCSI device %d not available\n", dev); - } - return 1; } - return CMD_RET_USAGE; - default: - /* at least 4 args */ - if (strcmp(argv[1],"read") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong blk = simple_strtoul(argv[3], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; - printf ("\nSCSI read: device %d block # %ld, count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_read(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf ("%ld blocks read: %s\n",n,(n==cnt) ? "OK" : "ERROR"); - return 0; - } else if (strcmp(argv[1], "write") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong blk = simple_strtoul(argv[3], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; - printf("\nSCSI write: device %d block # %ld, " - "count %ld ... ", - scsi_curr_dev, blk, cnt); - n = scsi_write(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); - printf("%ld blocks written: %s\n", n, - (n == cnt) ? "OK" : "ERROR"); - return 0; + if (!ok) + printf("\nno SCSI devices available\n"); + return 1; + } + return CMD_RET_USAGE; + case 3: + if (strncmp(argv[1], "dev", 3) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + printf("\nSCSI device %d: ", dev); + if (dev >= CONFIG_SYS_SCSI_MAX_DEVICE) { + printf("unknown device\n"); + return 1; } + printf("\n Device %d: ", dev); + dev_print(&scsi_dev_desc[dev]); + if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) + return 1; + scsi_curr_dev = dev; + printf("... is now current device\n"); + return 0; + } + if (strncmp(argv[1], "part", 4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + if (scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) + part_print(&scsi_dev_desc[dev]); + else + printf("\nSCSI device %d not available\n", dev); + return 1; + } + return CMD_RET_USAGE; + default: + /* at least 4 args */ + if (strcmp(argv[1], "read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong blk = simple_strtoul(argv[3], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + printf("\nSCSI read: device %d block # %ld, count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_read(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf("%ld blocks read: %s\n", n, + n == cnt ? "OK" : "ERROR"); + return 0; + } else if (strcmp(argv[1], "write") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong blk = simple_strtoul(argv[3], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + printf("\nSCSI write: device %d block # %ld, count %ld ... ", + scsi_curr_dev, blk, cnt); + n = scsi_write(&scsi_dev_desc[scsi_curr_dev], + blk, cnt, (ulong *)addr); + printf("%ld blocks written: %s\n", n, + n == cnt ? "OK" : "ERROR"); + return 0; + } } /* switch */ return CMD_RET_USAGE; } @@ -493,25 +488,24 @@ U_BOOT_CMD( /* copy src to dest, skipping leading and trailing blanks * and null terminate the string */ -void scsi_ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len) +void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len) { int start,end;
- start=0; - while(start<len) { - if(src[start]!=' ') + start = 0; + while (start < len) { + if (src[start] != ' ') break; start++; } - end=len-1; - while(end>start) { - if(src[end]!=' ') + end = len-1; + while (end > start) { + if (src[end] != ' ') break; end--; } - for( ; start<=end; start++) { - *dest++=src[start]; - } + for (; start <= end; start++) + *dest ++= src[start]; *dest='\0'; }
@@ -534,7 +528,7 @@ int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) { *capacity = 0;
- memset(pccb->cmd, 0, sizeof(pccb->cmd)); + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); pccb->cmd[0] = SCSI_RD_CAPAC10; pccb->cmd[1] = pccb->lun << 5; pccb->cmdlen = 10; @@ -559,8 +553,7 @@ int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) }
/* Read capacity (10) was insufficient. Use read capacity (16). */ - - memset(pccb->cmd, 0, sizeof(pccb->cmd)); + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); pccb->cmd[0] = SCSI_RD_CAPAC16; pccb->cmd[1] = 0x10; pccb->cmdlen = 16; @@ -597,14 +590,14 @@ int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) */ void scsi_setup_test_unit_ready(ccb * pccb) { - pccb->cmd[0]=SCSI_TST_U_RDY; - pccb->cmd[1]=pccb->lun<<5; - pccb->cmd[2]=0; - pccb->cmd[3]=0; - pccb->cmd[4]=0; - pccb->cmd[5]=0; - pccb->cmdlen=6; - pccb->msgout[0]=SCSI_IDENTIFY; /* NOT USED */ + pccb->cmd[0] = SCSI_TST_U_RDY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + pccb->cmd[4] = 0; + pccb->cmd[5] = 0; + pccb->cmdlen = 6; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ }
/********************************************************************************* @@ -618,50 +611,49 @@ void scsi_scan(int mode) unsigned long blksz; ccb* pccb=(ccb *)&tempccb;
- if(mode==1) { + if (mode == 1) printf("scanning bus for devices...\n"); - } - for(i=0;i<CONFIG_SYS_SCSI_MAX_DEVICE;i++) { - scsi_dev_desc[i].target=0xff; - scsi_dev_desc[i].lun=0xff; - scsi_dev_desc[i].lba=0; - scsi_dev_desc[i].blksz=0; - scsi_dev_desc[i].log2blksz = + for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++) { + scsi_dev_desc[i].target = 0xff; + scsi_dev_desc[i].lun = 0xff; + scsi_dev_desc[i].lba = 0; + scsi_dev_desc[i].blksz = 0; + scsi_dev_desc[i].log2blksz = LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); - scsi_dev_desc[i].type=DEV_TYPE_UNKNOWN; - scsi_dev_desc[i].vendor[0]=0; - scsi_dev_desc[i].product[0]=0; - scsi_dev_desc[i].revision[0]=0; + scsi_dev_desc[i].type = DEV_TYPE_UNKNOWN; + scsi_dev_desc[i].vendor[0] = 0; + scsi_dev_desc[i].product[0] = 0; + scsi_dev_desc[i].revision[0] = 0; scsi_dev_desc[i].removable = false; - scsi_dev_desc[i].if_type=IF_TYPE_SCSI; + scsi_dev_desc[i].if_type = IF_TYPE_SCSI; scsi_dev_desc[i].devnum = i; - scsi_dev_desc[i].part_type=PART_TYPE_UNKNOWN; - scsi_dev_desc[i].block_read=scsi_read; + scsi_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + scsi_dev_desc[i].block_read = scsi_read; scsi_dev_desc[i].block_write = scsi_write; } - scsi_max_devs=0; - for(i=0;i<CONFIG_SYS_SCSI_MAX_SCSI_ID;i++) { - pccb->target=i; - for(lun=0;lun<CONFIG_SYS_SCSI_MAX_LUN;lun++) { - pccb->lun=lun; - pccb->pdata=(unsigned char *)&tempbuff; - pccb->datalen=512; + scsi_max_devs = 0; + for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { + pccb->target = i; + for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) { + pccb->lun = lun; + pccb->pdata = (unsigned char *)&tempbuff; + pccb->datalen = 512; scsi_setup_inquiry(pccb); if (scsi_exec(pccb) != true) { if(pccb->contr_stat==SCSI_SEL_TIME_OUT) { - debug ("Selection timeout ID %d\n",pccb->target); + debug("Selection timeout ID %d\n", + pccb->target); continue; /* selection timeout => assuming no device present */ } scsi_print_error(pccb); continue; } - perq=tempbuff[0]; - modi=tempbuff[1]; - if((perq & 0x1f)==0x1f) { + perq = tempbuff[0]; + modi = tempbuff[1]; + if ((perq & 0x1f) == 0x1f) continue; /* skip unknown devices */ - } - if((modi&0x80)==0x80) /* drive is removable */ - scsi_dev_desc[scsi_max_devs].removable=true; + if ((modi & 0x80) == 0x80) /* drive is removable */ + scsi_dev_desc[scsi_max_devs].removable = true; /* get info for this device */ scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], &tempbuff[8], 8); @@ -669,14 +661,15 @@ void scsi_scan(int mode) &tempbuff[16], 16); scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0], &tempbuff[32], 4); - scsi_dev_desc[scsi_max_devs].target=pccb->target; - scsi_dev_desc[scsi_max_devs].lun=pccb->lun; + scsi_dev_desc[scsi_max_devs].target = pccb->target; + scsi_dev_desc[scsi_max_devs].lun = pccb->lun;
- pccb->datalen=0; + pccb->datalen = 0; scsi_setup_test_unit_ready(pccb); if (scsi_exec(pccb) != true) { - if (scsi_dev_desc[scsi_max_devs].removable == true) { - scsi_dev_desc[scsi_max_devs].type=perq; + if (scsi_dev_desc[scsi_max_devs].removable) { + scsi_dev_desc[scsi_max_devs].type = + perq; goto removable; } scsi_print_error(pccb); @@ -686,11 +679,11 @@ void scsi_scan(int mode) scsi_print_error(pccb); continue; } - scsi_dev_desc[scsi_max_devs].lba=capacity; - scsi_dev_desc[scsi_max_devs].blksz=blksz; + scsi_dev_desc[scsi_max_devs].lba = capacity; + scsi_dev_desc[scsi_max_devs].blksz = blksz; scsi_dev_desc[scsi_max_devs].log2blksz = LOG2(scsi_dev_desc[scsi_max_devs].blksz); - scsi_dev_desc[scsi_max_devs].type=perq; + scsi_dev_desc[scsi_max_devs].type = perq; part_init(&scsi_dev_desc[scsi_max_devs]); removable: if(mode==1) { @@ -700,8 +693,8 @@ removable: scsi_max_devs++; } /* next LUN */ } - if(scsi_max_devs>0) - scsi_curr_dev=0; + if (scsi_max_devs > 0) + scsi_curr_dev = 0; else scsi_curr_dev = -1;

On 1 May 2016 at 11:35, Simon Glass sjg@chromium.org wrote:
Update the code style of this file so that it passes checkpatch.pl.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
cmd/scsi.c | 459 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 226 insertions(+), 233 deletions(-)
Applied to u-boot-dm.

Adjust common/ide.c so that it passes most checkpatch.pl checks.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
cmd/ide.c | 57 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 28 deletions(-)
diff --git a/cmd/ide.c b/cmd/ide.c index c4c08c8..a46d0ac 100644 --- a/cmd/ide.c +++ b/cmd/ide.c @@ -58,13 +58,13 @@ struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; /* ------------------------------------------------------------------------- */
#ifdef CONFIG_IDE_RESET -static void ide_reset (void); +static void ide_reset(void); #else #define ide_reset() /* dummy */ #endif
static void ide_ident(struct blk_desc *dev_desc); -static uchar ide_wait (int dev, ulong t); +static uchar ide_wait(int dev, ulong t);
#define IDE_TIME_OUT 2000 /* 2 sec timeout */
@@ -72,14 +72,15 @@ static uchar ide_wait (int dev, ulong t);
#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
-static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); +static void ident_cpy(unsigned char *dest, unsigned char *src, + unsigned int len);
#ifndef CONFIG_SYS_ATA_PORT_ADDR #define CONFIG_SYS_ATA_PORT_ADDR(port) (port) #endif
#ifdef CONFIG_ATAPI -static void atapi_inquiry(struct blk_desc *dev_desc); +static void atapi_inquiry(struct blk_desc *dev_desc); static ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer); #endif @@ -150,7 +151,7 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return CMD_RET_USAGE; case 3: if (strncmp(argv[1], "dev", 3) == 0) { - int dev = (int) simple_strtoul(argv[2], NULL, 10); + int dev = (int)simple_strtoul(argv[2], NULL, 10);
printf("\nIDE device %d: ", dev); if (dev >= CONFIG_SYS_IDE_MAXDEVICE) { @@ -169,7 +170,7 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
return 0; } else if (strncmp(argv[1], "part", 4) == 0) { - int dev = (int) simple_strtoul(argv[2], NULL, 10); + int dev = (int)simple_strtoul(argv[2], NULL, 10);
if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { part_print(&ide_dev_desc[dev]); @@ -194,13 +195,13 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) #ifdef CONFIG_SYS_64BIT_LBA lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
- printf("\nIDE read: device %d block # %lld, count %ld ... ", - curr_device, blk, cnt); + printf("\nIDE read: device %d block # %lld, count %ld...", + curr_device, blk, cnt); #else lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
- printf("\nIDE read: device %d block # %ld, count %ld ... ", - curr_device, blk, cnt); + printf("\nIDE read: device %d block # %ld, count %ld...", + curr_device, blk, cnt); #endif
dev_desc = &ide_dev_desc[curr_device]; @@ -223,13 +224,13 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) #ifdef CONFIG_SYS_64BIT_LBA lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
- printf("\nIDE write: device %d block # %lld, count %ld ... ", - curr_device, blk, cnt); + printf("\nIDE write: device %d block # %lld, count %ld...", + curr_device, blk, cnt); #else lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
- printf("\nIDE write: device %d block # %ld, count %ld ... ", - curr_device, blk, cnt); + printf("\nIDE write: device %d block # %ld, count %ld...", + curr_device, blk, cnt); #endif n = ide_write(&ide_dev_desc[curr_device], blk, cnt, (ulong *)addr); @@ -833,7 +834,7 @@ ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, } IDE_READ_E: ide_led(DEVICE_LED(device), 0); /* LED off */ - return (n); + return n; }
/* ------------------------------------------------------------------------- */ @@ -922,7 +923,7 @@ ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, } WR_OUT: ide_led(DEVICE_LED(device), 0); /* LED off */ - return (n); + return n; }
/* ------------------------------------------------------------------------- */ @@ -974,7 +975,7 @@ static uchar ide_wait(int dev, ulong t) if (delay-- == 0) break; } - return (c); + return c; }
/* ------------------------------------------------------------------------- */ @@ -1098,7 +1099,7 @@ static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) if (delay-- == 0) break; } - return (c); + return c; }
/* @@ -1142,7 +1143,7 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen,
if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", - device, c); + device, c); err = 0xFF; goto AI_OUT; } @@ -1166,10 +1167,10 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, if (c & ATA_STAT_ERR) { err = (ide_inb(device, ATA_ERROR_REG)) >> 4; debug("atapi_issue 1 returned sense key %X status %02X\n", - err, c); + err, c); } else { printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", - ccb[0], c); + ccb[0], c); err = 0xFF; } goto AI_OUT; @@ -1190,7 +1191,7 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, } if (n != buflen) { debug("WARNING, transfer bytes %d not equal with requested %d\n", - n, buflen); + n, buflen); } if (n != 0) { /* data transfer */ debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); @@ -1220,7 +1221,7 @@ unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, } AI_OUT: ide_led(DEVICE_LED(device), 0); /* LED off */ - return (err); + return err; }
/* @@ -1297,7 +1298,7 @@ retry: ascq); error: debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); - return (0xFF); + return 0xFF; }
@@ -1402,8 +1403,8 @@ ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, unsigned char ccb[12]; /* Command descriptor block */ ulong cnt;
- debug("atapi_read dev %d start " LBAF " blocks " LBAF " buffer at %lX\n", - device, blknr, blkcnt, (ulong) buffer); + debug("atapi_read dev %d start " LBAF " blocks " LBAF + " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer);
do { if (blkcnt > ATAPI_READ_MAX_BLOCK) @@ -1428,14 +1429,14 @@ ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, (unsigned char *) buffer, cnt * ATAPI_READ_BLOCK_SIZE) == 0xFF) { - return (n); + return n; } n += cnt; blkcnt -= cnt; blknr += cnt; buffer += (cnt * ATAPI_READ_BLOCK_SIZE); } while (blkcnt > 0); - return (n); + return n; }
/* ------------------------------------------------------------------------- */

On 1 May 2016 at 11:35, Simon Glass sjg@chromium.org wrote:
Adjust common/ide.c so that it passes most checkpatch.pl checks.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
cmd/ide.c | 57 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 28 deletions(-)
Applied to u-boot-dm.

Reorder the code to avoid needing forward declarations. Fix up code style as needed.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
cmd/ide.c | 1924 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 946 insertions(+), 978 deletions(-)
diff --git a/cmd/ide.c b/cmd/ide.c index a46d0ac..db26f43 100644 --- a/cmd/ide.c +++ b/cmd/ide.c @@ -57,491 +57,518 @@ static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS]; struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; /* ------------------------------------------------------------------------- */
-#ifdef CONFIG_IDE_RESET -static void ide_reset(void); -#else -#define ide_reset() /* dummy */ -#endif - -static void ide_ident(struct blk_desc *dev_desc); -static uchar ide_wait(int dev, ulong t); - #define IDE_TIME_OUT 2000 /* 2 sec timeout */
#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */
#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */
-static void ident_cpy(unsigned char *dest, unsigned char *src, - unsigned int len); - #ifndef CONFIG_SYS_ATA_PORT_ADDR #define CONFIG_SYS_ATA_PORT_ADDR(port) (port) #endif
-#ifdef CONFIG_ATAPI -static void atapi_inquiry(struct blk_desc *dev_desc); -static ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer); +#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ +# define DEVICE_LED(x) 0 +# define LED_IDE1 1 +# define LED_IDE2 2 #endif
+#ifdef CONFIG_IDE_RESET +extern void ide_set_reset(int idereset);
-/* ------------------------------------------------------------------------- */ - -int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +static void ide_reset(void) { - int rcode = 0; - - switch (argc) { - case 0: - case 1: - return CMD_RET_USAGE; - case 2: - if (strncmp(argv[1], "res", 3) == 0) { - puts("\nReset IDE" -#ifdef CONFIG_IDE_8xx_DIRECT - " on PCMCIA " PCMCIA_SLOT_MSG -#endif - ": "); - - ide_init(); - return 0; - } else if (strncmp(argv[1], "inf", 3) == 0) { - int i; + int i;
- putc('\n'); + curr_device = -1; + for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) + ide_bus_ok[i] = 0; + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN;
- for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { - if (ide_dev_desc[i].type == DEV_TYPE_UNKNOWN) - continue; /* list only known devices */ - printf("IDE device %d: ", i); - dev_print(&ide_dev_desc[i]); - } - return 0; + ide_set_reset(1); /* assert reset */
- } else if (strncmp(argv[1], "dev", 3) == 0) { - if ((curr_device < 0) - || (curr_device >= CONFIG_SYS_IDE_MAXDEVICE)) { - puts("\nno IDE devices available\n"); - return 1; - } - printf("\nIDE device %d: ", curr_device); - dev_print(&ide_dev_desc[curr_device]); - return 0; - } else if (strncmp(argv[1], "part", 4) == 0) { - int dev, ok; + /* the reset signal shall be asserted for et least 25 us */ + udelay(25);
- for (ok = 0, dev = 0; - dev < CONFIG_SYS_IDE_MAXDEVICE; - ++dev) { - if (ide_dev_desc[dev].part_type != - PART_TYPE_UNKNOWN) { - ++ok; - if (dev) - putc('\n'); - part_print(&ide_dev_desc[dev]); - } - } - if (!ok) { - puts("\nno IDE devices available\n"); - rcode++; - } - return rcode; - } - return CMD_RET_USAGE; - case 3: - if (strncmp(argv[1], "dev", 3) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); + WATCHDOG_RESET();
- printf("\nIDE device %d: ", dev); - if (dev >= CONFIG_SYS_IDE_MAXDEVICE) { - puts("unknown device\n"); - return 1; - } - dev_print(&ide_dev_desc[dev]); - /*ide_print (dev); */ + /* de-assert RESET signal */ + ide_set_reset(0);
- if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; + /* wait 250 ms */ + for (i = 0; i < 250; ++i) + udelay(1000); +} +#else +#define ide_reset() /* dummy */ +#endif /* CONFIG_IDE_RESET */
- curr_device = dev; +/* + * Wait until Busy bit is off, or timeout (in ms) + * Return last status + */ +static uchar ide_wait(int dev, ulong t) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c;
- puts("... is now current device\n"); + while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { + udelay(100); + if (delay-- == 0) + break; + } + return c; +}
- return 0; - } else if (strncmp(argv[1], "part", 4) == 0) { - int dev = (int)simple_strtoul(argv[2], NULL, 10); +/* + * copy src to dest, skipping leading and trailing blanks and null + * terminate the string + * "len" is the size of available memory including the terminating '\0' + */ +static void ident_cpy(unsigned char *dst, unsigned char *src, + unsigned int len) +{ + unsigned char *end, *last;
- if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - part_print(&ide_dev_desc[dev]); - } else { - printf("\nIDE device %d not available\n", - dev); - rcode = 1; - } - return rcode; - } + last = dst; + end = src + len - 1;
- return CMD_RET_USAGE; - default: - /* at least 4 args */ + /* reserve space for '\0' */ + if (len < 2) + goto OUT;
- if (strcmp(argv[1], "read") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - struct blk_desc *dev_desc; - ulong n; + /* skip leading white space */ + while ((*src) && (src < end) && (*src == ' ')) + ++src;
-#ifdef CONFIG_SYS_64BIT_LBA - lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + /* copy string, omitting trailing white space */ + while ((*src) && (src < end)) { + *dst++ = *src; + if (*src++ != ' ') + last = dst; + } +OUT: + *last = '\0'; +}
- printf("\nIDE read: device %d block # %lld, count %ld...", - curr_device, blk, cnt); -#else - lbaint_t blk = simple_strtoul(argv[3], NULL, 16); +#ifdef CONFIG_ATAPI +/**************************************************************************** + * ATAPI Support + */
- printf("\nIDE read: device %d block # %ld, count %ld...", - curr_device, blk, cnt); -#endif +#if defined(CONFIG_IDE_SWAP_IO) +/* since ATAPI may use commands with not 4 bytes alligned length + * we have our own transfer functions, 2 bytes alligned */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf;
- dev_desc = &ide_dev_desc[curr_device]; - n = blk_dread(dev_desc, blk, cnt, (ulong *)addr); - /* flush cache after read */ - flush_cache(addr, - cnt * ide_dev_desc[curr_device].blksz); + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf;
- printf("%ld blocks read: %s\n", - n, (n == cnt) ? "OK" : "ERROR"); - if (n == cnt) - return 0; - else - return 1; - } else if (strcmp(argv[1], "write") == 0) { - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong cnt = simple_strtoul(argv[4], NULL, 16); - ulong n; + debug("in output data shorts base for read is %lx\n", + (unsigned long) pbuf);
-#ifdef CONFIG_SYS_64BIT_LBA - lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + while (shorts--) { + EIEIO; + *pbuf = *dbuf++; + } +}
- printf("\nIDE write: device %d block # %lld, count %ld...", - curr_device, blk, cnt); -#else - lbaint_t blk = simple_strtoul(argv[3], NULL, 16); +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf;
- printf("\nIDE write: device %d block # %ld, count %ld...", - curr_device, blk, cnt); -#endif - n = ide_write(&ide_dev_desc[curr_device], blk, cnt, - (ulong *)addr); + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf;
- printf("%ld blocks written: %s\n", - n, (n == cnt) ? "OK" : "ERROR"); - if (n == cnt) - return 0; - else - return 1; - } else { - return CMD_RET_USAGE; - } + debug("in input data shorts base for read is %lx\n", + (unsigned long) pbuf);
- return rcode; + while (shorts--) { + EIEIO; + *dbuf++ = *pbuf; } }
-int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) { - return common_diskboot(cmdtp, "ide", argc, argv); + outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); }
-/* ------------------------------------------------------------------------- */ - -__weak void ide_led(uchar led, uchar status) +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) { -#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */ - static uchar led_buffer; /* Buffer for current LED status */ - - uchar *led_port = LED_PORT; + insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +}
- if (status) /* switch LED on */ - led_buffer |= led; - else /* switch LED off */ - led_buffer &= ~led; +#endif /* CONFIG_IDE_SWAP_IO */
- *led_port = led_buffer; -#endif -} - -#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ -# define DEVICE_LED(x) 0 -# define LED_IDE1 1 -# define LED_IDE2 2 -#endif - -/* ------------------------------------------------------------------------- */ - -__weak void ide_outb(int dev, int port, unsigned char val) +/* + * Wait until (Status & mask) == res, or timeout (in ms) + * Return last status + * This is used since some ATAPI CD ROMs clears their Busy Bit first + * and then they set their DRQ Bit + */ +static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) { - debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n", - dev, port, val, - (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); + ulong delay = 10 * t; /* poll every 100 us */ + uchar c;
-#if defined(CONFIG_IDE_AHB) - if (port) { - /* write command */ - ide_write_register(dev, port, val); - } else { - /* write data */ - outb(val, (ATA_CURR_BASE(dev))); + /* prevents to read the status before valid */ + c = ide_inb(dev, ATA_DEV_CTL); + + while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { + /* break if error occurs (doesn't make sense to wait more) */ + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) + break; + udelay(100); + if (delay-- == 0) + break; } -#else - outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif + return c; }
-__weak unsigned char ide_inb(int dev, int port) +/* + * issue an atapi command + */ +unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, + unsigned char *buffer, int buflen) { - uchar val; - -#if defined(CONFIG_IDE_AHB) - val = ide_read_register(dev, port); -#else - val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif + unsigned char c, err, mask, res; + int n;
- debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", - dev, port, - (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val); - return val; -} + ide_led(DEVICE_LED(device), 1); /* LED on */
-void ide_init(void) -{ - unsigned char c; - int i, bus; + /* Select device + */ + mask = ATA_STAT_BUSY | ATA_STAT_DRQ; + res = 0; + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + printf("ATAPI_ISSUE: device %d not ready status %X\n", device, + c); + err = 0xFF; + goto AI_OUT; + } + /* write taskfile */ + ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_SECT_NUM, 0); + ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); + ide_outb(device, ATA_CYL_HIGH, + (unsigned char) ((buflen >> 8) & 0xFF)); + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
-#ifdef CONFIG_IDE_8xx_PCCARD - extern int ide_devices_found; /* Initialized in check_ide_device() */ -#endif /* CONFIG_IDE_8xx_PCCARD */ + ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); + udelay(50);
-#ifdef CONFIG_IDE_PREINIT - WATCHDOG_RESET(); + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res);
- if (ide_preinit()) { - puts("ide_preinit failed\n"); - return; + if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ + printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", + device, c); + err = 0xFF; + goto AI_OUT; } -#endif /* CONFIG_IDE_PREINIT */
- WATCHDOG_RESET(); + /* write command block */ + ide_output_data_shorts(device, (unsigned short *)ccb, ccblen / 2);
+ /* ATAPI Command written wait for completition */ + udelay(5000); /* device must set bsy */ + + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; /* - * Reset the IDE just to be sure. - * Light LED's to show + * if no data wait for DRQ = 0 BSY = 0 + * if data wait for DRQ = 1 BSY = 0 */ - ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */ - - /* ATAPI Drives seems to need a proper IDE Reset */ - ide_reset(); - -#ifdef CONFIG_IDE_INIT_POSTRESET - WATCHDOG_RESET(); - - if (ide_init_postreset()) { - puts("ide_preinit_postreset failed\n"); - return; + res = 0; + if (buflen) + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + if (c & ATA_STAT_ERR) { + err = (ide_inb(device, ATA_ERROR_REG)) >> 4; + debug("atapi_issue 1 returned sense key %X status %02X\n", + err, c); + } else { + printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", + ccb[0], c); + err = 0xFF; + } + goto AI_OUT; } -#endif /* CONFIG_IDE_INIT_POSTRESET */ + n = ide_inb(device, ATA_CYL_HIGH); + n <<= 8; + n += ide_inb(device, ATA_CYL_LOW); + if (n > buflen) { + printf("ERROR, transfer bytes %d requested only %d\n", n, + buflen); + err = 0xff; + goto AI_OUT; + } + if ((n == 0) && (buflen < 0)) { + printf("ERROR, transfer bytes %d requested %d\n", n, buflen); + err = 0xff; + goto AI_OUT; + } + if (n != buflen) { + debug("WARNING, transfer bytes %d not equal with requested %d\n", + n, buflen); + } + if (n != 0) { /* data transfer */ + debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); + /* we transfer shorts */ + n >>= 1; + /* ok now decide if it is an in or output */ + if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) { + debug("Write to device\n"); + ide_output_data_shorts(device, (unsigned short *)buffer, + n); + } else { + debug("Read from device @ %p shorts %d\n", buffer, n); + ide_input_data_shorts(device, (unsigned short *)buffer, + n); + } + } + udelay(5000); /* seems that some CD ROMs need this... */ + mask = ATA_STAT_BUSY | ATA_STAT_ERR; + res = 0; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + err = (ide_inb(device, ATA_ERROR_REG) >> 4); + debug("atapi_issue 2 returned sense key %X status %X\n", err, + c); + } else { + err = 0; + } +AI_OUT: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return err; +}
- /* - * Wait for IDE to get ready. - * According to spec, this can take up to 31 seconds! - */ - for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) { - int dev = - bus * (CONFIG_SYS_IDE_MAXDEVICE / - CONFIG_SYS_IDE_MAXBUS); +/* + * sending the command to atapi_issue. If an status other than good + * returns, an request_sense will be issued + */
-#ifdef CONFIG_IDE_8xx_PCCARD - /* Skip non-ide devices from probing */ - if ((ide_devices_found & (1 << bus)) == 0) { - ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ - continue; - } -#endif - printf("Bus %d: ", bus); +#define ATAPI_DRIVE_NOT_READY 100 +#define ATAPI_UNIT_ATTN 10
- ide_bus_ok[bus] = 0; +unsigned char atapi_issue_autoreq(int device, + unsigned char *ccb, + int ccblen, + unsigned char *buffer, int buflen) +{ + unsigned char sense_data[18], sense_ccb[12]; + unsigned char res, key, asc, ascq; + int notready, unitattn;
- /* Select device - */ - udelay(100000); /* 100 ms */ - ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); - udelay(100000); /* 100 ms */ - i = 0; - do { - udelay(10000); /* 10 ms */ + unitattn = ATAPI_UNIT_ATTN; + notready = ATAPI_DRIVE_NOT_READY;
- c = ide_inb(dev, ATA_STATUS); - i++; - if (i > (ATA_RESET_TIME * 100)) { - puts("** Timeout **\n"); - /* LED's off */ - ide_led((LED_IDE1 | LED_IDE2), 0); - return; - } - if ((i >= 100) && ((i % 100) == 0)) - putc('.'); +retry: + res = atapi_issue(device, ccb, ccblen, buffer, buflen); + if (res == 0) + return 0; /* Ok */
- } while (c & ATA_STAT_BUSY); + if (res == 0xFF) + return 0xFF; /* error */
- if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { - puts("not available "); - debug("Status = 0x%02X ", c); -#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ - } else if ((c & ATA_STAT_READY) == 0) { - puts("not available "); - debug("Status = 0x%02X ", c); -#endif - } else { - puts("OK "); - ide_bus_ok[bus] = 1; - } - WATCHDOG_RESET(); - } + debug("(auto_req)atapi_issue returned sense key %X\n", res);
- putc('\n'); + memset(sense_ccb, 0, sizeof(sense_ccb)); + memset(sense_data, 0, sizeof(sense_data)); + sense_ccb[0] = ATAPI_CMD_REQ_SENSE; + sense_ccb[4] = 18; /* allocation Length */
- ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + res = atapi_issue(device, sense_ccb, 12, sense_data, 18); + key = (sense_data[2] & 0xF); + asc = (sense_data[12]); + ascq = (sense_data[13]);
- curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { - int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - ide_dev_desc[i].if_type = IF_TYPE_IDE; - ide_dev_desc[i].devnum = i; - ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - ide_dev_desc[i].blksz = 0; - ide_dev_desc[i].log2blksz = - LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); - ide_dev_desc[i].lba = 0; - ide_dev_desc[i].block_read = ide_read; - ide_dev_desc[i].block_write = ide_write; - if (!ide_bus_ok[IDE_BUS(i)]) - continue; - ide_led(led, 1); /* LED on */ - ide_ident(&ide_dev_desc[i]); - ide_led(led, 0); /* LED off */ - dev_print(&ide_dev_desc[i]); + debug("ATAPI_CMD_REQ_SENSE returned %x\n", res); + debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", + sense_data[0], key, asc, ascq);
- if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { - /* initialize partition type */ - part_init(&ide_dev_desc[i]); - if (curr_device < 0) - curr_device = i; + if ((key == 0)) + return 0; /* ok device ready */ + + if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ + if (unitattn-- > 0) { + udelay(200 * 1000); + goto retry; } + printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); + goto error; } - WATCHDOG_RESET(); + if ((asc == 0x4) && (ascq == 0x1)) { + /* not ready, but will be ready soon */ + if (notready-- > 0) { + udelay(200 * 1000); + goto retry; + } + printf("Drive not ready, tried %d times\n", + ATAPI_DRIVE_NOT_READY); + goto error; + } + if (asc == 0x3a) { + debug("Media not present\n"); + goto error; + } + + printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, + ascq); +error: + debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); + return 0xFF; }
-/* ------------------------------------------------------------------------- */ +/* + * atapi_read: + * we transfer only one block per command, since the multiple DRQ per + * command is not yet implemented + */ +#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ +#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ +#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE)
-#ifdef CONFIG_PARTITIONS -struct blk_desc *ide_get_dev(int dev) +ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) { - return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; -} -#endif + int device = block_dev->devnum; + ulong n = 0; + unsigned char ccb[12]; /* Command descriptor block */ + ulong cnt;
-/* ------------------------------------------------------------------------- */ + debug("atapi_read dev %d start " LBAF " blocks " LBAF + " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer);
-/* We only need to swap data if we are running on a big endian cpu. */ -#if defined(__LITTLE_ENDIAN) -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) -{ - ide_input_data(dev, sect_buf, words); + do { + if (blkcnt > ATAPI_READ_MAX_BLOCK) + cnt = ATAPI_READ_MAX_BLOCK; + else + cnt = blkcnt; + + ccb[0] = ATAPI_CMD_READ_12; + ccb[1] = 0; /* reserved */ + ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ + ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ + ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; + ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ + ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ + ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; + ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; + ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ + ccb[10] = 0; /* reserved */ + ccb[11] = 0; /* reserved */ + + if (atapi_issue_autoreq(device, ccb, 12, + (unsigned char *)buffer, + cnt * ATAPI_READ_BLOCK_SIZE) + == 0xFF) { + return n; + } + n += cnt; + blkcnt -= cnt; + blknr += cnt; + buffer += (cnt * ATAPI_READ_BLOCK_SIZE); + } while (blkcnt > 0); + return n; } -#else -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) + +static void atapi_inquiry(struct blk_desc *dev_desc) { - volatile ushort *pbuf = - (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - ushort *dbuf = (ushort *) sect_buf; + unsigned char ccb[12]; /* Command descriptor block */ + unsigned char iobuf[64]; /* temp buf */ + unsigned char c; + int device;
- debug("in input swap data base for read is %lx\n", - (unsigned long) pbuf); + device = dev_desc->devnum; + dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ + dev_desc->block_read = atapi_read;
- while (words--) { -#ifdef __MIPS__ - *dbuf++ = swab16p((u16 *) pbuf); - *dbuf++ = swab16p((u16 *) pbuf); -#else - *dbuf++ = ld_le16(pbuf); - *dbuf++ = ld_le16(pbuf); -#endif /* !MIPS */ - } -} -#endif /* __LITTLE_ENDIAN */ + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf));
+ ccb[0] = ATAPI_CMD_INQUIRY; + ccb[4] = 40; /* allocation Legnth */ + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 40);
-#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_output_data(int dev, const ulong *sect_buf, int words) -{ - ushort *dbuf; - volatile ushort *pbuf; + debug("ATAPI_CMD_INQUIRY returned %x\n", c); + if (c != 0) + return;
- pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; - while (words--) { - EIEIO; - *pbuf = *dbuf++; - EIEIO; - *pbuf = *dbuf++; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data(int dev, const ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_write_data(dev, sect_buf, words); -#else - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); -#endif -} -#endif /* CONFIG_IDE_SWAP_IO */ + /* copy device ident strings */ + ident_cpy((unsigned char *)dev_desc->vendor, &iobuf[8], 8); + ident_cpy((unsigned char *)dev_desc->product, &iobuf[16], 16); + ident_cpy((unsigned char *)dev_desc->revision, &iobuf[32], 5);
-#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_input_data(int dev, ulong *sect_buf, int words) -{ - ushort *dbuf; - volatile ushort *pbuf; + dev_desc->lun = 0; + dev_desc->lba = 0; + dev_desc->blksz = 0; + dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); + dev_desc->type = iobuf[0] & 0x1f;
- pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; + if ((iobuf[1] & 0x80) == 0x80) + dev_desc->removable = 1; + else + dev_desc->removable = 0;
- debug("in input data base for read is %lx\n", (unsigned long) pbuf); + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_START_STOP; + ccb[4] = 0x03; /* start */
- while (words--) { - EIEIO; - *dbuf++ = *pbuf; - EIEIO; - *dbuf++ = *pbuf; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_input_data(int dev, ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_read_data(dev, sect_buf, words); -#else - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); + + debug("ATAPI_CMD_START_STOP returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); + + debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_READ_CAP; + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 8); + debug("ATAPI_CMD_READ_CAP returned %x\n", c); + if (c != 0) + return; + + debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", + iobuf[0], iobuf[1], iobuf[2], iobuf[3], + iobuf[4], iobuf[5], iobuf[6], iobuf[7]); + + dev_desc->lba = ((unsigned long) iobuf[0] << 24) + + ((unsigned long) iobuf[1] << 16) + + ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); + dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + + ((unsigned long) iobuf[5] << 16) + + ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); + dev_desc->log2blksz = LOG2(dev_desc->blksz); +#ifdef CONFIG_LBA48 + /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ + dev_desc->lba48 = 0; #endif + return; }
-#endif /* CONFIG_IDE_SWAP_IO */ +#endif /* CONFIG_ATAPI */
-/* ------------------------------------------------------------------------- - */ static void ide_ident(struct blk_desc *dev_desc) { unsigned char c; @@ -633,11 +660,11 @@ static void ide_ident(struct blk_desc *dev_desc)
ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS);
- ident_cpy((unsigned char *) dev_desc->revision, iop.fw_rev, + ident_cpy((unsigned char *)dev_desc->revision, iop.fw_rev, sizeof(dev_desc->revision)); - ident_cpy((unsigned char *) dev_desc->vendor, iop.model, + ident_cpy((unsigned char *)dev_desc->vendor, iop.model, sizeof(dev_desc->vendor)); - ident_cpy((unsigned char *) dev_desc->product, iop.serial_no, + ident_cpy((unsigned char *)dev_desc->product, iop.serial_no, sizeof(dev_desc->product)); #ifdef __LITTLE_ENDIAN /* @@ -711,737 +738,678 @@ static void ide_ident(struct blk_desc *dev_desc) #endif }
+/* ------------------------------------------------------------------------- */ + +int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int rcode = 0; + + switch (argc) { + case 0: + case 1: + return CMD_RET_USAGE; + case 2: + if (strncmp(argv[1], "res", 3) == 0) { + puts("\nReset IDE" +#ifdef CONFIG_IDE_8xx_DIRECT + " on PCMCIA " PCMCIA_SLOT_MSG +#endif + ": "); + + ide_init(); + return 0; + } else if (strncmp(argv[1], "inf", 3) == 0) { + int i; + + putc('\n'); + + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { + if (ide_dev_desc[i].type == DEV_TYPE_UNKNOWN) + continue; /* list only known devices */ + printf("IDE device %d: ", i); + dev_print(&ide_dev_desc[i]); + } + return 0; + + } else if (strncmp(argv[1], "dev", 3) == 0) { + if (curr_device < 0 || + curr_device >= CONFIG_SYS_IDE_MAXDEVICE) { + puts("\nno IDE devices available\n"); + return 1; + } + printf("\nIDE device %d: ", curr_device); + dev_print(&ide_dev_desc[curr_device]); + return 0; + } else if (strncmp(argv[1], "part", 4) == 0) { + int dev, ok; + + for (ok = 0, dev = 0; + dev < CONFIG_SYS_IDE_MAXDEVICE; + ++dev) { + if (ide_dev_desc[dev].part_type != + PART_TYPE_UNKNOWN) { + ++ok; + if (dev) + putc('\n'); + part_print(&ide_dev_desc[dev]); + } + } + if (!ok) { + puts("\nno IDE devices available\n"); + rcode++; + } + return rcode; + } + return CMD_RET_USAGE; + case 3: + if (strncmp(argv[1], "dev", 3) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10);
-/* ------------------------------------------------------------------------- */ + printf("\nIDE device %d: ", dev); + if (dev >= CONFIG_SYS_IDE_MAXDEVICE) { + puts("unknown device\n"); + return 1; + } + dev_print(&ide_dev_desc[dev]); + /*ide_print (dev); */
-ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char c; - unsigned char pwrsave = 0; /* power save */ + if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) + return 1;
-#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; + curr_device = dev;
- if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n", - device, blknr, blkcnt, (ulong) buffer); + puts("... is now current device\n");
- ide_led(DEVICE_LED(device), 1); /* LED on */ + return 0; + } else if (strncmp(argv[1], "part", 4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10);
- /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = ide_wait(device, IDE_TIME_OUT); + if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { + part_print(&ide_dev_desc[dev]); + } else { + printf("\nIDE device %d not available\n", + dev); + rcode = 1; + } + return rcode; + }
- if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } + return CMD_RET_USAGE; + default: + /* at least 4 args */
- /* first check if the drive is in Powersaving mode, if yes, - * increase the timeout value */ - ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR); - udelay(50); + if (strcmp(argv[1], "read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + struct blk_desc *dev_desc; + ulong n;
- c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ +#ifdef CONFIG_SYS_64BIT_LBA + lbaint_t blk = simple_strtoull(argv[3], NULL, 16);
- if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { - printf("No Powersaving mode %X\n", c); - } else { - c = ide_inb(device, ATA_SECT_CNT); - debug("Powersaving %02X\n", c); - if (c == 0) - pwrsave = 1; - } + printf("\nIDE read: device %d block # %lld, count %ld...", + curr_device, blk, cnt); +#else + lbaint_t blk = simple_strtoul(argv[3], NULL, 16);
+ printf("\nIDE read: device %d block # %ld, count %ld...", + curr_device, blk, cnt); +#endif
- while (blkcnt-- > 0) { + dev_desc = &ide_dev_desc[curr_device]; + n = blk_dread(dev_desc, blk, cnt, (ulong *)addr); + /* flush cache after read */ + flush_cache(addr, + cnt * ide_dev_desc[curr_device].blksz);
- c = ide_wait(device, IDE_TIME_OUT); + printf("%ld blocks read: %s\n", + n, (n == cnt) ? "OK" : "ERROR"); + if (n == cnt) + return 0; + else + return 1; + } else if (strcmp(argv[1], "write") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n;
- if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - break; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); #ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); + lbaint_t blk = simple_strtoull(argv[3], NULL, 16); + + printf("\nIDE write: device %d block # %lld, count %ld...", + curr_device, blk, cnt); #else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); + lbaint_t blk = simple_strtoul(argv[3], NULL, 16); + + printf("\nIDE write: device %d block # %ld, count %ld...", + curr_device, blk, cnt); #endif + n = ide_write(&ide_dev_desc[curr_device], blk, cnt, + (ulong *)addr); + + printf("%ld blocks written: %s\n", n, + n == cnt ? "OK" : "ERROR"); + if (n == cnt) + return 0; + else + return 1; + } else { + return CMD_RET_USAGE; } -#endif - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); - ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
-#ifdef CONFIG_LBA48 - if (lba48) { - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT); + return rcode; + } +}
- } else -#endif - { - ide_outb(device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); - ide_outb(device, ATA_COMMAND, ATA_CMD_READ); - } +int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + return common_diskboot(cmdtp, "ide", argc, argv); +}
- udelay(50); +/* ------------------------------------------------------------------------- */
- if (pwrsave) { - /* may take up to 4 sec */ - c = ide_wait(device, IDE_SPIN_UP_TIME_OUT); - pwrsave = 0; - } else { - /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); - } +__weak void ide_led(uchar led, uchar status) +{ +#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */ + static uchar led_buffer; /* Buffer for current LED status */
- if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF ": status " - "%#02x\n", device, blknr, c); - break; - } + uchar *led_port = LED_PORT;
- ide_input_data(device, buffer, ATA_SECTORWORDS); - (void) ide_inb(device, ATA_STATUS); /* clear IRQ */ + if (status) /* switch LED on */ + led_buffer |= led; + else /* switch LED off */ + led_buffer &= ~led;
- ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; - } -IDE_READ_E: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return n; + *led_port = led_buffer; +#endif }
/* ------------------------------------------------------------------------- */
+__weak void ide_outb(int dev, int port, unsigned char val) +{ + debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n", + dev, port, val, + (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)));
-ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - const void *buffer) +#if defined(CONFIG_IDE_AHB) + if (port) { + /* write command */ + ide_write_register(dev, port, val); + } else { + /* write data */ + outb(val, (ATA_CURR_BASE(dev))); + } +#else + outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif +} + +__weak unsigned char ide_inb(int dev, int port) +{ + uchar val; + +#if defined(CONFIG_IDE_AHB) + val = ide_read_register(dev, port); +#else + val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif + + debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", + dev, port, + (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val); + return val; +} + +void ide_init(void) { - int device = block_dev->devnum; - ulong n = 0; unsigned char c; + int i, bus;
-#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; +#ifdef CONFIG_IDE_8xx_PCCARD + extern int ide_devices_found; /* Initialized in check_ide_device() */ +#endif /* CONFIG_IDE_8xx_PCCARD */
- if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; +#ifdef CONFIG_IDE_PREINIT + WATCHDOG_RESET(); + + if (ide_preinit()) { + puts("ide_preinit failed\n"); + return; } -#endif +#endif /* CONFIG_IDE_PREINIT */
- ide_led(DEVICE_LED(device), 1); /* LED on */ + WATCHDOG_RESET();
- /* Select device + /* + * Reset the IDE just to be sure. + * Light LED's to show */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */
- while (blkcnt-- > 0) { + /* ATAPI Drives seems to need a proper IDE Reset */ + ide_reset();
- c = ide_wait(device, IDE_TIME_OUT); +#ifdef CONFIG_IDE_INIT_POSTRESET + WATCHDOG_RESET();
- if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto WR_OUT; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); -#ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); -#else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); -#endif + if (ide_init_postreset()) { + puts("ide_preinit_postreset failed\n"); + return; + } +#endif /* CONFIG_IDE_INIT_POSTRESET */ + + /* + * Wait for IDE to get ready. + * According to spec, this can take up to 31 seconds! + */ + for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) { + int dev = + bus * (CONFIG_SYS_IDE_MAXDEVICE / + CONFIG_SYS_IDE_MAXBUS); + +#ifdef CONFIG_IDE_8xx_PCCARD + /* Skip non-ide devices from probing */ + if ((ide_devices_found & (1 << bus)) == 0) { + ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + continue; } #endif - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); - ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); + printf("Bus %d: ", bus);
-#ifdef CONFIG_LBA48 - if (lba48) { - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT); + ide_bus_ok[bus] = 0;
- } else -#endif - { - ide_outb(device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); - ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE); - } + /* Select device + */ + udelay(100000); /* 100 ms */ + ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); + udelay(100000); /* 100 ms */ + i = 0; + do { + udelay(10000); /* 10 ms */
- udelay(50); + c = ide_inb(dev, ATA_STATUS); + i++; + if (i > (ATA_RESET_TIME * 100)) { + puts("** Timeout **\n"); + /* LED's off */ + ide_led((LED_IDE1 | LED_IDE2), 0); + return; + } + if ((i >= 100) && ((i % 100) == 0)) + putc('.');
- /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); + } while (c & ATA_STAT_BUSY);
- if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF ": status " - "%#02x\n", device, blknr, c); - goto WR_OUT; + if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { + puts("not available "); + debug("Status = 0x%02X ", c); +#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ + } else if ((c & ATA_STAT_READY) == 0) { + puts("not available "); + debug("Status = 0x%02X ", c); +#endif + } else { + puts("OK "); + ide_bus_ok[bus] = 1; } - - ide_output_data(device, buffer, ATA_SECTORWORDS); - c = ide_inb(device, ATA_STATUS); /* clear IRQ */ - ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; + WATCHDOG_RESET(); } -WR_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return n; -} - -/* ------------------------------------------------------------------------- */ - -/* - * copy src to dest, skipping leading and trailing blanks and null - * terminate the string - * "len" is the size of available memory including the terminating '\0' - */ -static void ident_cpy(unsigned char *dst, unsigned char *src, - unsigned int len) -{ - unsigned char *end, *last;
- last = dst; - end = src + len - 1; + putc('\n');
- /* reserve space for '\0' */ - if (len < 2) - goto OUT; + ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */
- /* skip leading white space */ - while ((*src) && (src < end) && (*src == ' ')) - ++src; + curr_device = -1; + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { + int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; + ide_dev_desc[i].if_type = IF_TYPE_IDE; + ide_dev_desc[i].devnum = i; + ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + ide_dev_desc[i].blksz = 0; + ide_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); + ide_dev_desc[i].lba = 0; + ide_dev_desc[i].block_read = ide_read; + ide_dev_desc[i].block_write = ide_write; + if (!ide_bus_ok[IDE_BUS(i)]) + continue; + ide_led(led, 1); /* LED on */ + ide_ident(&ide_dev_desc[i]); + ide_led(led, 0); /* LED off */ + dev_print(&ide_dev_desc[i]);
- /* copy string, omitting trailing white space */ - while ((*src) && (src < end)) { - *dst++ = *src; - if (*src++ != ' ') - last = dst; + if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { + /* initialize partition type */ + part_init(&ide_dev_desc[i]); + if (curr_device < 0) + curr_device = i; + } } -OUT: - *last = '\0'; + WATCHDOG_RESET(); }
/* ------------------------------------------------------------------------- */
-/* - * Wait until Busy bit is off, or timeout (in ms) - * Return last status - */ -static uchar ide_wait(int dev, ulong t) +#ifdef CONFIG_PARTITIONS +struct blk_desc *ide_get_dev(int dev) { - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { - udelay(100); - if (delay-- == 0) - break; - } - return c; + return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; } +#endif
/* ------------------------------------------------------------------------- */
-#ifdef CONFIG_IDE_RESET -extern void ide_set_reset(int idereset); - -static void ide_reset(void) +/* We only need to swap data if we are running on a big endian cpu. */ +#if defined(__LITTLE_ENDIAN) +__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) { - int i; - - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) - ide_bus_ok[i] = 0; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - - ide_set_reset(1); /* assert reset */ - - /* the reset signal shall be asserted for et least 25 us */ - udelay(25); - - WATCHDOG_RESET(); - - /* de-assert RESET signal */ - ide_set_reset(0); - - /* wait 250 ms */ - for (i = 0; i < 250; ++i) - udelay(1000); + ide_input_data(dev, sect_buf, words); } +#else +__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) +{ + volatile ushort *pbuf = + (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + ushort *dbuf = (ushort *)sect_buf;
-#endif /* CONFIG_IDE_RESET */ - -/* ------------------------------------------------------------------------- */ + debug("in input swap data base for read is %lx\n", + (unsigned long) pbuf);
-#if defined(CONFIG_OF_IDE_FIXUP) -int ide_device_present(int dev) -{ - if (dev >= CONFIG_SYS_IDE_MAXBUS) - return 0; - return (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1); + while (words--) { +#ifdef __MIPS__ + *dbuf++ = swab16p((u16 *)pbuf); + *dbuf++ = swab16p((u16 *)pbuf); +#else + *dbuf++ = ld_le16(pbuf); + *dbuf++ = ld_le16(pbuf); +#endif /* !MIPS */ + } } -#endif -/* ------------------------------------------------------------------------- */ +#endif /* __LITTLE_ENDIAN */
-#ifdef CONFIG_ATAPI -/**************************************************************************** - * ATAPI Support - */
#if defined(CONFIG_IDE_SWAP_IO) -/* since ATAPI may use commands with not 4 bytes alligned length - * we have our own transfer functions, 2 bytes alligned */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +__weak void ide_output_data(int dev, const ulong *sect_buf, int words) { ushort *dbuf; volatile ushort *pbuf;
- pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; - - debug("in output data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + while (words--) { + EIEIO; + *pbuf = *dbuf++; EIEIO; *pbuf = *dbuf++; } } +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_output_data(int dev, const ulong *sect_buf, int words) +{ +#if defined(CONFIG_IDE_AHB) + ide_write_data(dev, sect_buf, words); +#else + outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); +#endif +} +#endif /* CONFIG_IDE_SWAP_IO */
-__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +#if defined(CONFIG_IDE_SWAP_IO) +__weak void ide_input_data(int dev, ulong *sect_buf, int words) { ushort *dbuf; volatile ushort *pbuf;
- pbuf = (ushort *) (ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *) sect_buf; + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf;
- debug("in input data shorts base for read is %lx\n", - (unsigned long) pbuf); + debug("in input data base for read is %lx\n", (unsigned long) pbuf);
- while (shorts--) { + while (words--) { + EIEIO; + *dbuf++ = *pbuf; EIEIO; *dbuf++ = *pbuf; } } - #else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +__weak void ide_input_data(int dev, ulong *sect_buf, int words) { - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +#if defined(CONFIG_IDE_AHB) + ide_read_data(dev, sect_buf, words); +#else + insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); +#endif }
#endif /* CONFIG_IDE_SWAP_IO */
-/* - * Wait until (Status & mask) == res, or timeout (in ms) - * Return last status - * This is used since some ATAPI CD ROMs clears their Busy Bit first - * and then they set their DRQ Bit - */ -static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) +/* ------------------------------------------------------------------------- */ + +ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) { - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; + int device = block_dev->devnum; + ulong n = 0; + unsigned char c; + unsigned char pwrsave = 0; /* power save */
- /* prevents to read the status before valid */ - c = ide_inb(dev, ATA_DEV_CTL); +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0;
- while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { - /* break if error occurs (doesn't make sense to wait more) */ - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) - break; - udelay(100); - if (delay-- == 0) - break; + if (blknr & 0x0000fffff0000000ULL) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; } - return c; -} - -/* - * issue an atapi command - */ -unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char c, err, mask, res; - int n; +#endif + debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n", + device, blknr, blkcnt, (ulong) buffer);
ide_led(DEVICE_LED(device), 1); /* LED on */
/* Select device */ - mask = ATA_STAT_BUSY | ATA_STAT_DRQ; - res = 0; - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - printf("ATAPI_ISSUE: device %d not ready status %X\n", device, - c); - err = 0xFF; - goto AI_OUT; - } - /* write taskfile */ - ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_SECT_NUM, 0); - ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); - ide_outb(device, ATA_CYL_HIGH, - (unsigned char) ((buflen >> 8) & 0xFF)); ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = ide_wait(device, IDE_TIME_OUT);
- ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); - udelay(50); - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - - if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ - printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", - device, c); - err = 0xFF; - goto AI_OUT; - } - - /* write command block */ - ide_output_data_shorts(device, (unsigned short *) ccb, ccblen / 2); - - /* ATAPI Command written wait for completition */ - udelay(5000); /* device must set bsy */ - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - /* - * if no data wait for DRQ = 0 BSY = 0 - * if data wait for DRQ = 1 BSY = 0 - */ - res = 0; - if (buflen) - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - if (c & ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG)) >> 4; - debug("atapi_issue 1 returned sense key %X status %02X\n", - err, c); - } else { - printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", - ccb[0], c); - err = 0xFF; - } - goto AI_OUT; - } - n = ide_inb(device, ATA_CYL_HIGH); - n <<= 8; - n += ide_inb(device, ATA_CYL_LOW); - if (n > buflen) { - printf("ERROR, transfer bytes %d requested only %d\n", n, - buflen); - err = 0xff; - goto AI_OUT; - } - if ((n == 0) && (buflen < 0)) { - printf("ERROR, transfer bytes %d requested %d\n", n, buflen); - err = 0xff; - goto AI_OUT; - } - if (n != buflen) { - debug("WARNING, transfer bytes %d not equal with requested %d\n", - n, buflen); - } - if (n != 0) { /* data transfer */ - debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); - /* we transfer shorts */ - n >>= 1; - /* ok now decide if it is an in or output */ - if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) { - debug("Write to device\n"); - ide_output_data_shorts(device, - (unsigned short *) buffer, n); - } else { - debug("Read from device @ %p shorts %d\n", buffer, n); - ide_input_data_shorts(device, - (unsigned short *) buffer, n); - } - } - udelay(5000); /* seems that some CD ROMs need this... */ - mask = ATA_STAT_BUSY | ATA_STAT_ERR; - res = 0; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG) >> 4); - debug("atapi_issue 2 returned sense key %X status %X\n", err, - c); - } else { - err = 0; + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto IDE_READ_E; } -AI_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return err; -} - -/* - * sending the command to atapi_issue. If an status other than good - * returns, an request_sense will be issued - */ - -#define ATAPI_DRIVE_NOT_READY 100 -#define ATAPI_UNIT_ATTN 10 - -unsigned char atapi_issue_autoreq(int device, - unsigned char *ccb, - int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char sense_data[18], sense_ccb[12]; - unsigned char res, key, asc, ascq; - int notready, unitattn; - - unitattn = ATAPI_UNIT_ATTN; - notready = ATAPI_DRIVE_NOT_READY; - -retry: - res = atapi_issue(device, ccb, ccblen, buffer, buflen); - if (res == 0) - return 0; /* Ok */ - - if (res == 0xFF) - return 0xFF; /* error */ - - debug("(auto_req)atapi_issue returned sense key %X\n", res); - - memset(sense_ccb, 0, sizeof(sense_ccb)); - memset(sense_data, 0, sizeof(sense_data)); - sense_ccb[0] = ATAPI_CMD_REQ_SENSE; - sense_ccb[4] = 18; /* allocation Length */ - - res = atapi_issue(device, sense_ccb, 12, sense_data, 18); - key = (sense_data[2] & 0xF); - asc = (sense_data[12]); - ascq = (sense_data[13]);
- debug("ATAPI_CMD_REQ_SENSE returned %x\n", res); - debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", - sense_data[0], key, asc, ascq); + /* first check if the drive is in Powersaving mode, if yes, + * increase the timeout value */ + ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR); + udelay(50);
- if ((key == 0)) - return 0; /* ok device ready */ + c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */
- if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ - if (unitattn-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); - goto error; - } - if ((asc == 0x4) && (ascq == 0x1)) { - /* not ready, but will be ready soon */ - if (notready-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Drive not ready, tried %d times\n", - ATAPI_DRIVE_NOT_READY); - goto error; + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto IDE_READ_E; } - if (asc == 0x3a) { - debug("Media not present\n"); - goto error; + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + printf("No Powersaving mode %X\n", c); + } else { + c = ide_inb(device, ATA_SECT_CNT); + debug("Powersaving %02X\n", c); + if (c == 0) + pwrsave = 1; }
- printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, - ascq); -error: - debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); - return 0xFF; -}
+ while (blkcnt-- > 0) {
-static void atapi_inquiry(struct blk_desc *dev_desc) -{ - unsigned char ccb[12]; /* Command descriptor block */ - unsigned char iobuf[64]; /* temp buf */ - unsigned char c; - int device; + c = ide_wait(device, IDE_TIME_OUT);
- device = dev_desc->devnum; - dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ - dev_desc->block_read = atapi_read; + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + break; + } +#ifdef CONFIG_LBA48 + if (lba48) { + /* write high bits */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); +#ifdef CONFIG_SYS_64BIT_LBA + ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); +#else + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); +#endif + } +#endif + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); + ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
- memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); +#ifdef CONFIG_LBA48 + if (lba48) { + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT);
- ccb[0] = ATAPI_CMD_INQUIRY; - ccb[4] = 40; /* allocation Legnth */ - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 40); + } else +#endif + { + ide_outb(device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); + ide_outb(device, ATA_COMMAND, ATA_CMD_READ); + }
- debug("ATAPI_CMD_INQUIRY returned %x\n", c); - if (c != 0) - return; + udelay(50);
- /* copy device ident strings */ - ident_cpy((unsigned char *) dev_desc->vendor, &iobuf[8], 8); - ident_cpy((unsigned char *) dev_desc->product, &iobuf[16], 16); - ident_cpy((unsigned char *) dev_desc->revision, &iobuf[32], 5); + if (pwrsave) { + /* may take up to 4 sec */ + c = ide_wait(device, IDE_SPIN_UP_TIME_OUT); + pwrsave = 0; + } else { + /* can't take over 500 ms */ + c = ide_wait(device, IDE_TIME_OUT); + }
- dev_desc->lun = 0; - dev_desc->lba = 0; - dev_desc->blksz = 0; - dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); - dev_desc->type = iobuf[0] & 0x1f; + if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != + ATA_STAT_DRQ) { + printf("Error (no IRQ) dev %d blk " LBAF + ": status %#02x\n", device, blknr, c); + break; + }
- if ((iobuf[1] & 0x80) == 0x80) - dev_desc->removable = 1; - else - dev_desc->removable = 0; + ide_input_data(device, buffer, ATA_SECTORWORDS); + (void) ide_inb(device, ATA_STATUS); /* clear IRQ */
- memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_START_STOP; - ccb[4] = 0x03; /* start */ + ++n; + ++blknr; + buffer += ATA_BLOCKSIZE; + } +IDE_READ_E: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return n; +}
- c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0); +/* ------------------------------------------------------------------------- */
- debug("ATAPI_CMD_START_STOP returned %x\n", c); - if (c != 0) - return;
- memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 0); +ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +{ + int device = block_dev->devnum; + ulong n = 0; + unsigned char c;
- debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); - if (c != 0) - return; +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0;
- memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_READ_CAP; - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *) iobuf, 8); - debug("ATAPI_CMD_READ_CAP returned %x\n", c); - if (c != 0) - return; + if (blknr & 0x0000fffff0000000ULL) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; + } +#endif
- debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", - iobuf[0], iobuf[1], iobuf[2], iobuf[3], - iobuf[4], iobuf[5], iobuf[6], iobuf[7]); + ide_led(DEVICE_LED(device), 1); /* LED on */
- dev_desc->lba = ((unsigned long) iobuf[0] << 24) + - ((unsigned long) iobuf[1] << 16) + - ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); - dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + - ((unsigned long) iobuf[5] << 16) + - ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); - dev_desc->log2blksz = LOG2(dev_desc->blksz); -#ifdef CONFIG_LBA48 - /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ - dev_desc->lba48 = 0; -#endif - return; -} + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device));
+ while (blkcnt-- > 0) { + c = ide_wait(device, IDE_TIME_OUT);
-/* - * atapi_read: - * we transfer only one block per command, since the multiple DRQ per - * command is not yet implemented - */ -#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ -#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ -#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto WR_OUT; + } +#ifdef CONFIG_LBA48 + if (lba48) { + /* write high bits */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); +#ifdef CONFIG_SYS_64BIT_LBA + ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); +#else + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); +#endif + } +#endif + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); + ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF);
-ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char ccb[12]; /* Command descriptor block */ - ulong cnt; +#ifdef CONFIG_LBA48 + if (lba48) { + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT);
- debug("atapi_read dev %d start " LBAF " blocks " LBAF - " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); + } else +#endif + { + ide_outb(device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); + ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE); + }
- do { - if (blkcnt > ATAPI_READ_MAX_BLOCK) - cnt = ATAPI_READ_MAX_BLOCK; - else - cnt = blkcnt; + udelay(50);
- ccb[0] = ATAPI_CMD_READ_12; - ccb[1] = 0; /* reserved */ - ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ - ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ - ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; - ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ - ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ - ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; - ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; - ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ - ccb[10] = 0; /* reserved */ - ccb[11] = 0; /* reserved */ + /* can't take over 500 ms */ + c = ide_wait(device, IDE_TIME_OUT);
- if (atapi_issue_autoreq(device, ccb, 12, - (unsigned char *) buffer, - cnt * ATAPI_READ_BLOCK_SIZE) - == 0xFF) { - return n; + if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != + ATA_STAT_DRQ) { + printf("Error (no IRQ) dev %d blk " LBAF + ": status %#02x\n", device, blknr, c); + goto WR_OUT; } - n += cnt; - blkcnt -= cnt; - blknr += cnt; - buffer += (cnt * ATAPI_READ_BLOCK_SIZE); - } while (blkcnt > 0); + + ide_output_data(device, buffer, ATA_SECTORWORDS); + c = ide_inb(device, ATA_STATUS); /* clear IRQ */ + ++n; + ++blknr; + buffer += ATA_BLOCKSIZE; + } +WR_OUT: + ide_led(DEVICE_LED(device), 0); /* LED off */ return n; }
/* ------------------------------------------------------------------------- */
-#endif /* CONFIG_ATAPI */ +#if defined(CONFIG_OF_IDE_FIXUP) +int ide_device_present(int dev) +{ + if (dev >= CONFIG_SYS_IDE_MAXBUS) + return 0; + return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1; +} +#endif +/* ------------------------------------------------------------------------- */
U_BOOT_CMD(ide, 5, 1, do_ide, "IDE sub-system",

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Reorder the code to avoid needing forward declarations. Fix up code style as needed.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
cmd/ide.c | 1924 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 946 insertions(+), 978 deletions(-)
Applied to u-boot-dm.

This file has a few coding style problems. Fix these to make future updates easier.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
cmd/sata.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/cmd/sata.c b/cmd/sata.c index 8748cce..b1a64d9 100644 --- a/cmd/sata.c +++ b/cmd/sata.c @@ -105,25 +105,27 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) case 1: return CMD_RET_USAGE; case 2: - if (strncmp(argv[1],"inf", 3) == 0) { + if (strncmp(argv[1], "inf", 3) == 0) { int i; + putc('\n'); for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) { if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN) continue; - printf ("SATA device %d: ", i); + printf("SATA device %d: ", i); dev_print(&sata_dev_desc[i]); } return 0; - } else if (strncmp(argv[1],"dev", 3) == 0) { - if ((sata_curr_device < 0) || (sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE)) { + } else if (strncmp(argv[1], "dev", 3) == 0) { + if (sata_curr_device < 0 || + sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE) { puts("\nno SATA devices available\n"); return 1; } printf("\nSATA device %d: ", sata_curr_device); dev_print(&sata_dev_desc[sata_curr_device]); return 0; - } else if (strncmp(argv[1],"part",4) == 0) { + } else if (strncmp(argv[1], "part", 4) == 0) { int dev, ok;
for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) {

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
This file has a few coding style problems. Fix these to make future updates easier.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
cmd/sata.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
Applied to u-boot-dm.

This option currently enables both the command and the SCSI functionality. Rename the existing option to CONFIG_SCSI since most of the code relates to the feature.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
README | 4 ++-- api/api_storage.c | 2 +- arch/arm/include/asm/arch-ls102xa/config.h | 2 +- board/mpl/pip405/README | 6 +++--- cmd/Makefile | 4 ++-- cmd/disk.c | 2 +- common/board_r.c | 4 ++-- disk/part.c | 2 +- drivers/block/sym53c8xx.c | 2 +- fs/fat/fat.c | 2 +- include/config_cmd_all.h | 2 +- include/config_distro_bootcmd.h | 6 +++--- include/config_fallbacks.h | 2 +- include/configs/MPC8544DS.h | 2 +- include/configs/MPC8572DS.h | 2 +- include/configs/MPC8610HPCD.h | 2 +- include/configs/MPC8641HPCN.h | 2 +- include/configs/PIP405.h | 2 +- include/configs/am57xx_evm.h | 2 +- include/configs/cm_t54.h | 2 +- include/configs/db-88f6820-gp.h | 2 +- include/configs/dra7xx_evm.h | 2 +- include/configs/efi-x86.h | 2 +- include/configs/galileo.h | 2 +- include/configs/highbank.h | 2 +- include/configs/ls1043aqds.h | 2 +- include/configs/ls2080aqds.h | 2 +- include/configs/ls2080ardb.h | 2 +- include/configs/omap5_uevm.h | 2 +- include/configs/qemu-x86.h | 2 +- include/configs/sunxi-common.h | 2 +- include/configs/x86-common.h | 2 +- include/configs/xilinx_zynqmp.h | 2 +- 33 files changed, 40 insertions(+), 40 deletions(-)
diff --git a/README b/README index 88ff837..33dc788 100644 --- a/README +++ b/README @@ -1066,7 +1066,7 @@ The following options need to be configured: CONFIG_CMD_RUN run command in env variable CONFIG_CMD_SANDBOX * sb command to access sandbox features CONFIG_CMD_SAVES * save S record dump - CONFIG_CMD_SCSI * SCSI Support + CONFIG_SCSI * SCSI Support CONFIG_CMD_SDRAM * print SDRAM configuration information (requires CONFIG_CMD_I2C) CONFIG_CMD_SETGETDCR Support for DCR Register access @@ -1254,7 +1254,7 @@ The following options need to be configured: CONFIG_MTD_PARTITIONS Memory Technology Device partition table.
If IDE or SCSI support is enabled (CONFIG_CMD_IDE or - CONFIG_CMD_SCSI) you must configure support for at + CONFIG_SCSI) you must configure support for at least one non-MTD partition type as well.
- IDE Reset method: diff --git a/api/api_storage.c b/api/api_storage.c index 8c30c56..d425a9a 100644 --- a/api/api_storage.c +++ b/api/api_storage.c @@ -67,7 +67,7 @@ void dev_stor_init(void) specs[ENUM_SATA].type = DEV_TYP_STOR | DT_STOR_SATA; specs[ENUM_SATA].name = "sata"; #endif -#if defined(CONFIG_CMD_SCSI) +#if defined(CONFIG_SCSI) specs[ENUM_SCSI].max_dev = CONFIG_SYS_SCSI_MAX_DEVICE; specs[ENUM_SCSI].enum_started = 0; specs[ENUM_SCSI].enum_ended = 0; diff --git a/arch/arm/include/asm/arch-ls102xa/config.h b/arch/arm/include/asm/arch-ls102xa/config.h index 267bd17..d77c04a 100644 --- a/arch/arm/include/asm/arch-ls102xa/config.h +++ b/arch/arm/include/asm/arch-ls102xa/config.h @@ -82,7 +82,7 @@ /* SATA */ #define AHCI_BASE_ADDR (CONFIG_SYS_IMMR + 0x02200000) #define CONFIG_BOARD_LATE_INIT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT diff --git a/board/mpl/pip405/README b/board/mpl/pip405/README index e900c56..f039817 100644 --- a/board/mpl/pip405/README +++ b/board/mpl/pip405/README @@ -32,8 +32,8 @@ Changed files: - include/cmd_bsp.h added PIP405 commands definitions - include/cmd_condefs.h added Floppy and SCSI support - include/cmd_disk.h changed to work with block device description -- include/config_LANTEC.h excluded CONFIG_CMD_FDC and CONFIG_CMD_SCSI -- include/config_hymod.h excluded CONFIG_CMD_FDC and CONFIG_CMD_SCSI +- include/config_LANTEC.h excluded CONFIG_CMD_FDC and CONFIG_SCSI +- include/config_hymod.h excluded CONFIG_CMD_FDC and CONFIG_SCSI - include/flash.h added INTEL_ID_28F320C3T 0x88C488C4 - include/i2c.h added "defined(CONFIG_PIP405)" - include/image.h added IH_OS_U_BOOT, IH_TYPE_FIRMWARE @@ -86,7 +86,7 @@ section "Changes".
New Commands: ------------- -CONFIG_CMD_SCSI SCSI Support +CONFIG_SCSI SCSI Support CONFIG_CMF_FDC Floppy disk support
IDE additions: diff --git a/cmd/Makefile b/cmd/Makefile index f95759e..6612a3b 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -112,7 +112,7 @@ obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o obj-$(CONFIG_SANDBOX) += host.o obj-$(CONFIG_CMD_SATA) += sata.o obj-$(CONFIG_CMD_SF) += sf.o -obj-$(CONFIG_CMD_SCSI) += scsi.o +obj-$(CONFIG_SCSI) += scsi.o obj-$(CONFIG_CMD_SHA1SUM) += sha1sum.o obj-$(CONFIG_CMD_SETEXPR) += setexpr.o obj-$(CONFIG_CMD_SOFTSWITCH) += softswitch.o @@ -157,7 +157,7 @@ endif # !CONFIG_SPL_BUILD
ifdef CONFIG_SPL_BUILD ifdef CONFIG_SPL_SATA_SUPPORT -obj-$(CONFIG_CMD_SCSI) += scsi.o +obj-$(CONFIG_SCSI) += scsi.o endif endif # CONFIG_SPL_BUILD
diff --git a/cmd/disk.c b/cmd/disk.c index 2fd1717..fcc4123 100644 --- a/cmd/disk.c +++ b/cmd/disk.c @@ -8,7 +8,7 @@ #include <command.h> #include <part.h>
-#if defined(CONFIG_CMD_IDE) || defined(CONFIG_CMD_SCSI) || \ +#if defined(CONFIG_CMD_IDE) || defined(CONFIG_SCSI) || \ defined(CONFIG_USB_STORAGE) int common_diskboot(cmd_tbl_t *cmdtp, const char *intf, int argc, char *const argv[]) diff --git a/common/board_r.c b/common/board_r.c index ad02549..d959ad3 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -620,7 +620,7 @@ static int initr_ambapp_print(void) } #endif
-#if defined(CONFIG_CMD_SCSI) +#if defined(CONFIG_SCSI) static int initr_scsi(void) { puts("SCSI: "); @@ -923,7 +923,7 @@ init_fnc_t init_sequence_r[] = { initr_ambapp_print, #endif #endif -#ifdef CONFIG_CMD_SCSI +#ifdef CONFIG_SCSI INIT_FUNC_WATCHDOG_RESET initr_scsi, #endif diff --git a/disk/part.c b/disk/part.c index 543cab8..2613bff 100644 --- a/disk/part.c +++ b/disk/part.c @@ -28,7 +28,7 @@ const struct block_drvr block_drvr[] = { #if defined(CONFIG_CMD_SATA) {.name = "sata", .get_dev = sata_get_dev, }, #endif -#if defined(CONFIG_CMD_SCSI) +#if defined(CONFIG_SCSI) { .name = "scsi", .get_dev = scsi_get_dev, }, #endif #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) diff --git a/drivers/block/sym53c8xx.c b/drivers/block/sym53c8xx.c index c7c40af..5daede7 100644 --- a/drivers/block/sym53c8xx.c +++ b/drivers/block/sym53c8xx.c @@ -33,7 +33,7 @@ #define PRINTF(fmt,args...) #endif
-#if defined(CONFIG_CMD_SCSI) && defined(CONFIG_SCSI_SYM53C8XX) +#if defined(CONFIG_SCSI) && defined(CONFIG_SCSI_SYM53C8XX)
#undef SCSI_SINGLE_STEP /* diff --git a/fs/fat/fat.c b/fs/fat/fat.c index 600a90e..826bd85 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -1254,7 +1254,7 @@ int file_fat_detectfs(void)
#if defined(CONFIG_CMD_IDE) || \ defined(CONFIG_CMD_SATA) || \ - defined(CONFIG_CMD_SCSI) || \ + defined(CONFIG_SCSI) || \ defined(CONFIG_CMD_USB) || \ defined(CONFIG_MMC) printf("Interface: "); diff --git a/include/config_cmd_all.h b/include/config_cmd_all.h index ed502a1..b5fd6c6 100644 --- a/include/config_cmd_all.h +++ b/include/config_cmd_all.h @@ -45,7 +45,7 @@ #define CONFIG_CMD_READ /* Read data from partition */ #define CONFIG_CMD_SANDBOX /* sb command to access sandbox features */ #define CONFIG_CMD_SAVES /* save S record dump */ -#define CONFIG_CMD_SCSI /* SCSI Support */ +#define CONFIG_SCSI /* SCSI Support */ #define CONFIG_CMD_SDRAM /* SDRAM DIMM SPD info printout */ #define CONFIG_CMD_TERMINAL /* built-in Serial Terminal */ #define CONFIG_CMD_UBI /* UBI Support */ diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index 7f67344..5a8d7f2 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -165,7 +165,7 @@ BOOT_TARGET_DEVICES_references_SATA_without_CONFIG_CMD_SATA #endif
-#ifdef CONFIG_CMD_SCSI +#ifdef CONFIG_SCSI #define BOOTENV_RUN_SCSI_INIT "run scsi_init; " #define BOOTENV_SET_SCSI_NEED_INIT "setenv scsi_need_init; " #define BOOTENV_SHARED_SCSI \ @@ -185,9 +185,9 @@ #define BOOTENV_SET_SCSI_NEED_INIT #define BOOTENV_SHARED_SCSI #define BOOTENV_DEV_SCSI \ - BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_CMD_SCSI + BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_SCSI #define BOOTENV_DEV_NAME_SCSI \ - BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_CMD_SCSI + BOOT_TARGET_DEVICES_references_SCSI_without_CONFIG_SCSI #endif
#ifdef CONFIG_CMD_IDE diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h index 2666191..2ad54b7 100644 --- a/include/config_fallbacks.h +++ b/include/config_fallbacks.h @@ -45,7 +45,7 @@ /* Rather than repeat this expression each time, add a define for it */ #if defined(CONFIG_CMD_IDE) || \ defined(CONFIG_CMD_SATA) || \ - defined(CONFIG_CMD_SCSI) || \ + defined(CONFIG_SCSI) || \ defined(CONFIG_CMD_USB) || \ defined(CONFIG_CMD_PART) || \ defined(CONFIG_CMD_GPT) || \ diff --git a/include/configs/MPC8544DS.h b/include/configs/MPC8544DS.h index 6202dff..47445b9 100644 --- a/include/configs/MPC8544DS.h +++ b/include/configs/MPC8544DS.h @@ -373,7 +373,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
#if defined(CONFIG_PCI) #define CONFIG_CMD_PCI - #define CONFIG_CMD_SCSI + #define CONFIG_SCSI #endif
/* diff --git a/include/configs/MPC8572DS.h b/include/configs/MPC8572DS.h index 9144f32..6c723fe 100644 --- a/include/configs/MPC8572DS.h +++ b/include/configs/MPC8572DS.h @@ -576,7 +576,7 @@
#if defined(CONFIG_PCI) #define CONFIG_CMD_PCI -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #endif
/* diff --git a/include/configs/MPC8610HPCD.h b/include/configs/MPC8610HPCD.h index 88ca4f3..cec1910 100644 --- a/include/configs/MPC8610HPCD.h +++ b/include/configs/MPC8610HPCD.h @@ -449,7 +449,7 @@
#if defined(CONFIG_PCI) #define CONFIG_CMD_PCI -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #endif
#define CONFIG_WATCHDOG /* watchdog enabled */ diff --git a/include/configs/MPC8641HPCN.h b/include/configs/MPC8641HPCN.h index 4ba2163..7015ce9 100644 --- a/include/configs/MPC8641HPCN.h +++ b/include/configs/MPC8641HPCN.h @@ -610,7 +610,7 @@ extern unsigned long get_board_sys_clk(unsigned long dummy);
#if defined(CONFIG_PCI) #define CONFIG_CMD_PCI - #define CONFIG_CMD_SCSI + #define CONFIG_SCSI #endif
#undef CONFIG_WATCHDOG /* watchdog disabled */ diff --git a/include/configs/PIP405.h b/include/configs/PIP405.h index 4bd06a4..4506d86 100644 --- a/include/configs/PIP405.h +++ b/include/configs/PIP405.h @@ -43,7 +43,7 @@ #define CONFIG_CMD_EEPROM #define CONFIG_CMD_REGINFO #define CONFIG_CMD_FDC -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_CMD_DATE #define CONFIG_CMD_SDRAM #define CONFIG_CMD_SAVES diff --git a/include/configs/am57xx_evm.h b/include/configs/am57xx_evm.h index 32d7d4d..d53b0fd 100644 --- a/include/configs/am57xx_evm.h +++ b/include/configs/am57xx_evm.h @@ -75,7 +75,7 @@
/* SATA */ #define CONFIG_BOARD_LATE_INIT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT diff --git a/include/configs/cm_t54.h b/include/configs/cm_t54.h index 9b13aa6..ac6103c 100644 --- a/include/configs/cm_t54.h +++ b/include/configs/cm_t54.h @@ -60,7 +60,7 @@ #define CONFIG_SPL_SATA_BOOT_DEVICE 0 #define CONFIG_SYS_SATA_FAT_BOOT_PARTITION 1
-#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT diff --git a/include/configs/db-88f6820-gp.h b/include/configs/db-88f6820-gp.h index d84dde3..3539a62 100644 --- a/include/configs/db-88f6820-gp.h +++ b/include/configs/db-88f6820-gp.h @@ -27,7 +27,7 @@ #define CONFIG_SYS_NO_FLASH /* Declare no flash (NOR/SPI) */ #define CONFIG_CMD_ENV #define CONFIG_CMD_PCI -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI
/* I2C */ #define CONFIG_SYS_I2C diff --git a/include/configs/dra7xx_evm.h b/include/configs/dra7xx_evm.h index 79b6c09..8a0cd66 100644 --- a/include/configs/dra7xx_evm.h +++ b/include/configs/dra7xx_evm.h @@ -230,7 +230,7 @@
/* SATA */ #define CONFIG_BOARD_LATE_INIT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT diff --git a/include/configs/efi-x86.h b/include/configs/efi-x86.h index 6dd0b32..95e46c5 100644 --- a/include/configs/efi-x86.h +++ b/include/configs/efi-x86.h @@ -18,7 +18,7 @@ #undef CONFIG_VIDEO #undef CONFIG_CFB_CONSOLE #undef CONFIG_SCSI_AHCI -#undef CONFIG_CMD_SCSI +#undef CONFIG_SCSI #undef CONFIG_INTEL_ICH6_GPIO #undef CONFIG_USB_EHCI_PCI
diff --git a/include/configs/galileo.h b/include/configs/galileo.h index 2f1f6d4..40f7fba 100644 --- a/include/configs/galileo.h +++ b/include/configs/galileo.h @@ -29,7 +29,7 @@
/* SATA is not supported in Quark SoC */ #undef CONFIG_SCSI_AHCI -#undef CONFIG_CMD_SCSI +#undef CONFIG_SCSI
/* Video is not supported in Quark SoC */ #undef CONFIG_VIDEO diff --git a/include/configs/highbank.h b/include/configs/highbank.h index 3bce12b..5cefddc 100644 --- a/include/configs/highbank.h +++ b/include/configs/highbank.h @@ -51,7 +51,7 @@ /* * Command line configuration. */ -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI
#define CONFIG_BOOT_RETRY_TIME -1 #define CONFIG_RESET_TO_RETRY diff --git a/include/configs/ls1043aqds.h b/include/configs/ls1043aqds.h index d71a229..af1f73d 100644 --- a/include/configs/ls1043aqds.h +++ b/include/configs/ls1043aqds.h @@ -108,7 +108,7 @@ unsigned long get_board_ddr_clk(void); #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_DOS_PARTITION #define CONFIG_BOARD_LATE_INIT
diff --git a/include/configs/ls2080aqds.h b/include/configs/ls2080aqds.h index 2d7567f..f8c9e51 100644 --- a/include/configs/ls2080aqds.h +++ b/include/configs/ls2080aqds.h @@ -44,7 +44,7 @@ unsigned long get_board_ddr_clk(void); #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_DOS_PARTITION #define CONFIG_BOARD_LATE_INIT
diff --git a/include/configs/ls2080ardb.h b/include/configs/ls2080ardb.h index 5bec509..4577919 100644 --- a/include/configs/ls2080ardb.h +++ b/include/configs/ls2080ardb.h @@ -62,7 +62,7 @@ unsigned long get_board_sys_clk(void); #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_DOS_PARTITION #define CONFIG_BOARD_LATE_INIT
diff --git a/include/configs/omap5_uevm.h b/include/configs/omap5_uevm.h index 86cefa3..4ddc492 100644 --- a/include/configs/omap5_uevm.h +++ b/include/configs/omap5_uevm.h @@ -115,7 +115,7 @@ /* Max time to hold reset on this board, see doc/README.omap-reset-time */ #define CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC 16296
-#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT diff --git a/include/configs/qemu-x86.h b/include/configs/qemu-x86.h index b0d2ffe..476d37d 100644 --- a/include/configs/qemu-x86.h +++ b/include/configs/qemu-x86.h @@ -43,7 +43,7 @@ #define CONFIG_ATAPI
#undef CONFIG_SCSI_AHCI -#undef CONFIG_CMD_SCSI +#undef CONFIG_SCSI #else #define CONFIG_SCSI_DEV_LIST \ {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_AHCI} diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 2406115..ac2d931 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -125,7 +125,7 @@ #define CONFIG_SYS_SCSI_MAX_LUN 1 #define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ CONFIG_SYS_SCSI_MAX_LUN) -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #endif
#define CONFIG_SETUP_MEMORY_TAGS diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h index a2822e0..b79f47b 100644 --- a/include/configs/x86-common.h +++ b/include/configs/x86-common.h @@ -100,7 +100,7 @@ #define CONFIG_CMD_IRQ #define CONFIG_CMD_PCI #define CONFIG_CMD_GETTIME -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI
#define CONFIG_CMD_ZBOOT
diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h index 060bca9..6b8e3ea 100644 --- a/include/configs/xilinx_zynqmp.h +++ b/include/configs/xilinx_zynqmp.h @@ -201,7 +201,7 @@ #define CONFIG_SYS_SCSI_MAX_LUN 1 #define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ CONFIG_SYS_SCSI_MAX_LUN) -#define CONFIG_CMD_SCSI +#define CONFIG_SCSI #endif
#define CONFIG_SYS_BOOTM_LEN (60 * 1024 * 1024)

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
This option currently enables both the command and the SCSI functionality. Rename the existing option to CONFIG_SCSI since most of the code relates to the feature.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
README | 4 ++-- api/api_storage.c | 2 +- arch/arm/include/asm/arch-ls102xa/config.h | 2 +- board/mpl/pip405/README | 6 +++--- cmd/Makefile | 4 ++-- cmd/disk.c | 2 +- common/board_r.c | 4 ++-- disk/part.c | 2 +- drivers/block/sym53c8xx.c | 2 +- fs/fat/fat.c | 2 +- include/config_cmd_all.h | 2 +- include/config_distro_bootcmd.h | 6 +++--- include/config_fallbacks.h | 2 +- include/configs/MPC8544DS.h | 2 +- include/configs/MPC8572DS.h | 2 +- include/configs/MPC8610HPCD.h | 2 +- include/configs/MPC8641HPCN.h | 2 +- include/configs/PIP405.h | 2 +- include/configs/am57xx_evm.h | 2 +- include/configs/cm_t54.h | 2 +- include/configs/db-88f6820-gp.h | 2 +- include/configs/dra7xx_evm.h | 2 +- include/configs/efi-x86.h | 2 +- include/configs/galileo.h | 2 +- include/configs/highbank.h | 2 +- include/configs/ls1043aqds.h | 2 +- include/configs/ls2080aqds.h | 2 +- include/configs/ls2080ardb.h | 2 +- include/configs/omap5_uevm.h | 2 +- include/configs/qemu-x86.h | 2 +- include/configs/sunxi-common.h | 2 +- include/configs/x86-common.h | 2 +- include/configs/xilinx_zynqmp.h | 2 +- 33 files changed, 40 insertions(+), 40 deletions(-)
Applied to u-boot-dm.

There is quite a bit of duplicated common code related to block devices in the IDE and SCSI implementations.
Create some helper functions that can be used to reduce the duplication. These rely on a linker list of interface-type drivers
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Adjust newline output in blk_list_part() - Mention MMC partition 0 in the comments
drivers/block/Makefile | 4 + drivers/block/blk_legacy.c | 261 +++++++++++++++++++++++++++++++++++++++++++++ include/blk.h | 195 +++++++++++++++++++++++++++++++++ 3 files changed, 460 insertions(+) create mode 100644 drivers/block/blk_legacy.c
diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 3f75934..436b79f 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -7,6 +7,10 @@
obj-$(CONFIG_BLK) += blk-uclass.o
+ifndef CONFIG_BLK +obj-y += blk_legacy.o +endif + obj-$(CONFIG_AHCI) += ahci-uclass.o obj-$(CONFIG_SCSI_AHCI) += ahci.o obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o diff --git a/drivers/block/blk_legacy.c b/drivers/block/blk_legacy.c new file mode 100644 index 0000000..7b90a8a --- /dev/null +++ b/drivers/block/blk_legacy.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2016 Google, Inc + * Written by Simon Glass sjg@chromium.org + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <linux/err.h> + +struct blk_driver *blk_driver_lookup_type(int if_type) +{ + struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver); + const int n_ents = ll_entry_count(struct blk_driver, blk_driver); + struct blk_driver *entry; + + for (entry = drv; entry != drv + n_ents; entry++) { + if (if_type == entry->if_type) + return entry; + } + + /* Not found */ + return NULL; +} + +static struct blk_driver *blk_driver_lookup_typename(const char *if_typename) +{ + struct blk_driver *drv = ll_entry_start(struct blk_driver, blk_driver); + const int n_ents = ll_entry_count(struct blk_driver, blk_driver); + struct blk_driver *entry; + + for (entry = drv; entry != drv + n_ents; entry++) { + if (!strcmp(if_typename, entry->if_typename)) + return entry; + } + + /* Not found */ + return NULL; +} + +/** + * get_desc() - Get the block device descriptor for the given device number + * + * @drv: Legacy block driver + * @devnum: Device number (0 = first) + * @descp: Returns block device descriptor on success + * @return 0 on success, -ENODEV if there is no such device, -ENOSYS if the + * driver does not provide a way to find a device, or other -ve on other + * error. + */ +static int get_desc(struct blk_driver *drv, int devnum, struct blk_desc **descp) +{ + if (drv->desc) { + if (devnum < 0 || devnum >= drv->max_devs) + return -ENODEV; + *descp = &drv->desc[devnum]; + return 0; + } + if (!drv->get_dev) + return -ENOSYS; + + return drv->get_dev(devnum, descp); +} + +#ifdef HAVE_BLOCK_DEVICE +int blk_list_part(enum if_type if_type) +{ + struct blk_driver *drv; + struct blk_desc *desc; + int devnum, ok; + bool first = true; + + drv = blk_driver_lookup_type(if_type); + if (!drv) + return -ENOSYS; + for (ok = 0, devnum = 0; devnum < drv->max_devs; ++devnum) { + if (get_desc(drv, devnum, &desc)) + continue; + if (desc->part_type != PART_TYPE_UNKNOWN) { + ++ok; + if (!first) + putc('\n'); + part_print(desc); + first = false; + } + } + if (!ok) + return -ENODEV; + + return 0; +} + +int blk_print_part_devnum(enum if_type if_type, int devnum) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int ret; + + if (!drv) + return -ENOSYS; + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + if (desc->type == DEV_TYPE_UNKNOWN) + return -ENOENT; + part_print(desc); + + return 0; +} + +void blk_list_devices(enum if_type if_type) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int i; + + if (!drv) + return; + for (i = 0; i < drv->max_devs; ++i) { + if (get_desc(drv, i, &desc)) + continue; + if (desc->type == DEV_TYPE_UNKNOWN) + continue; /* list only known devices */ + printf("Device %d: ", i); + dev_print(desc); + } +} + +int blk_print_device_num(enum if_type if_type, int devnum) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int ret; + + if (!drv) + return -ENOSYS; + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + printf("\n%s device %d: ", drv->if_typename, devnum); + dev_print(desc); + + return 0; +} + +int blk_show_device(enum if_type if_type, int devnum) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int ret; + + if (!drv) + return -ENOSYS; + printf("\nDevice %d: ", devnum); + if (devnum >= drv->max_devs) { + puts("unknown device\n"); + return -ENODEV; + } + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + dev_print(desc); + + if (desc->type == DEV_TYPE_UNKNOWN) + return -ENOENT; + + return 0; +} +#endif /* HAVE_BLOCK_DEVICE */ + +struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + + if (!drv) + return NULL; + + if (get_desc(drv, devnum, &desc)) + return NULL; + + return desc; +} + +int blk_dselect_hwpart(struct blk_desc *desc, int hwpart) +{ + struct blk_driver *drv = blk_driver_lookup_type(desc->if_type); + + if (!drv) + return -ENOSYS; + if (drv->select_hwpart) + return drv->select_hwpart(desc, hwpart); + + return 0; +} + +struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum) +{ + struct blk_driver *drv = blk_driver_lookup_typename(if_typename); + struct blk_desc *desc; + + if (!drv) + return NULL; + + if (get_desc(drv, devnum, &desc)) + return NULL; + + return desc; +} + +ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, void *buffer) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + ulong n; + int ret; + + if (!drv) + return -ENOSYS; + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + n = desc->block_read(desc, start, blkcnt, buffer); + if (IS_ERR_VALUE(n)) + return n; + + /* flush cache after read */ + flush_cache((ulong)buffer, blkcnt * desc->blksz); + + return n; +} + +ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int ret; + + if (!drv) + return -ENOSYS; + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + return desc->block_write(desc, start, blkcnt, buffer); +} + +int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart) +{ + struct blk_driver *drv = blk_driver_lookup_type(if_type); + struct blk_desc *desc; + int ret; + + if (!drv) + return -ENOSYS; + ret = get_desc(drv, devnum, &desc); + if (ret) + return ret; + return drv->select_hwpart(desc, hwpart); +} diff --git a/include/blk.h b/include/blk.h index f624671..a562c10 100644 --- a/include/blk.h +++ b/include/blk.h @@ -340,6 +340,201 @@ static inline ulong blk_derase(struct blk_desc *block_dev, lbaint_t start, blkcache_invalidate(block_dev->if_type, block_dev->devnum); return block_dev->block_erase(block_dev, start, blkcnt); } + +/** + * struct blk_driver - Driver for block interface types + * + * This provides access to the block devices for each interface type. One + * driver should be provided using U_BOOT_LEGACY_BLK() for each interface + * type that is to be supported. + * + * @if_typename: Interface type name + * @if_type: Interface type + * @max_devs: Maximum number of devices supported + * @desc: Pointer to list of devices for this interface type, + * or NULL to use @get_dev() instead + */ +struct blk_driver { + const char *if_typename; + enum if_type if_type; + int max_devs; + struct blk_desc *desc; + /** + * get_dev() - get a pointer to a block device given its number + * + * Each interface allocates its own devices and typically + * struct blk_desc is contained with the interface's data structure. + * There is no global numbering for block devices. This method allows + * the device for an interface type to be obtained when @desc is NULL. + * + * @devnum: Device number (0 for first device on that interface, + * 1 for second, etc. + * @descp: Returns pointer to the block device on success + * @return 0 if OK, -ve on error + */ + int (*get_dev)(int devnum, struct blk_desc **descp); + + /** + * select_hwpart() - Select a hardware partition + * + * Some devices (e.g. MMC) can support partitioning at the hardware + * level. This is quite separate from the normal idea of + * software-based partitions. MMC hardware partitions must be + * explicitly selected. Once selected only the region of the device + * covered by that partition is accessible. + * + * The MMC standard provides for two boot partitions (numbered 1 and 2), + * rpmb (3), and up to 4 addition general-purpose partitions (4-7). + * Partition 0 is the main user-data partition. + * + * @desc: Block device descriptor + * @hwpart: Hardware partition number to select. 0 means the main + * user-data partition, 1 is the first partition, 2 is + * the second, etc. + * @return 0 if OK, other value for an error + */ + int (*select_hwpart)(struct blk_desc *desc, int hwpart); +}; + +/* + * Declare a new U-Boot legacy block driver. New drivers should use driver + * model (UCLASS_BLK). + */ +#define U_BOOT_LEGACY_BLK(__name) \ + ll_entry_declare(struct blk_driver, __name, blk_driver) + +struct blk_driver *blk_driver_lookup_type(int if_type); + #endif /* !CONFIG_BLK */
+/** + * blk_get_devnum_by_typename() - Get a block device by type and number + * + * This looks through the available block devices of the given type, returning + * the one with the given @devnum. + * + * @if_type: Block device type + * @devnum: Device number + * @return point to block device descriptor, or NULL if not found + */ +struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum); + +/** + * blk_get_devnum_by_type() - Get a block device by type name, and number + * + * This looks up the block device type based on @if_typename, then calls + * blk_get_devnum_by_type(). + * + * @if_typename: Block device type name + * @devnum: Device number + * @return point to block device descriptor, or NULL if not found + */ +struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, + int devnum); + +/** + * blk_dselect_hwpart() - select a hardware partition + * + * This selects a hardware partition (such as is supported by MMC). The block + * device size may change as this effectively points the block device to a + * partition at the hardware level. See the select_hwpart() method above. + * + * @desc: Block device descriptor for the device to select + * @hwpart: Partition number to select + * @return 0 if OK, -ve on error + */ +int blk_dselect_hwpart(struct blk_desc *desc, int hwpart); + +/** + * blk_list_part() - list the partitions for block devices of a given type + * + * This looks up the partition type for each block device of type @if_type, + * then displays a list of partitions. + * + * @if_type: Block device type + * @return 0 if OK, -ENODEV if there is none of that type + */ +int blk_list_part(enum if_type if_type); + +/** + * blk_list_devices() - list the block devices of a given type + * + * This lists each block device of the type @if_type, showing the capacity + * as well as type-specific information. + * + * @if_type: Block device type + */ +void blk_list_devices(enum if_type if_type); + +/** + * blk_show_device() - show information about a given block device + * + * This shows the block device capacity as well as type-specific information. + * + * @if_type: Block device type + * @devnum: Device number + * @return 0 if OK, -ENODEV for invalid device number + */ +int blk_show_device(enum if_type if_type, int devnum); + +/** + * blk_print_device_num() - show information about a given block device + * + * This is similar to blk_show_device() but returns an error if the block + * device type is unknown. + * + * @if_type: Block device type + * @devnum: Device number + * @return 0 if OK, -ENODEV for invalid device number, -ENOENT if the block + * device is not connected + */ +int blk_print_device_num(enum if_type if_type, int devnum); + +/** + * blk_print_part_devnum() - print the partition information for a device + * + * @if_type: Block device type + * @devnum: Device number + * @return 0 if OK, -ENOENT if the block device is not connected, -ENOSYS if + * the interface type is not supported, other -ve on other error + */ +int blk_print_part_devnum(enum if_type if_type, int devnum); + +/** + * blk_read_devnum() - read blocks from a device + * + * @if_type: Block device type + * @devnum: Device number + * @blkcnt: Number of blocks to read + * @buffer: Address to write data to + * @return number of blocks read, or -ve error number on error + */ +ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, void *buffer); + +/** + * blk_write_devnum() - write blocks to a device + * + * @if_type: Block device type + * @devnum: Device number + * @blkcnt: Number of blocks to write + * @buffer: Address to read data from + * @return number of blocks written, or -ve error number on error + */ +ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, const void *buffer); + +/** + * blk_select_hwpart_devnum() - select a hardware partition + * + * This is similar to blk_dselect_hwpart() but it looks up the interface and + * device number. + * + * @if_type: Block device type + * @devnum: Device number + * @hwpart: Partition number to select + * @return 0 if OK, -ve on error + */ +int blk_select_hwpart_devnum(enum if_type if_type, int devnum, int hwpart); + #endif

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
There is quite a bit of duplicated common code related to block devices in the IDE and SCSI implementations.
Create some helper functions that can be used to reduce the duplication. These rely on a linker list of interface-type drivers
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Adjust newline output in blk_list_part()
- Mention MMC partition 0 in the comments
drivers/block/Makefile | 4 + drivers/block/blk_legacy.c | 261 +++++++++++++++++++++++++++++++++++++++++++++ include/blk.h | 195 +++++++++++++++++++++++++++++++++ 3 files changed, 460 insertions(+) create mode 100644 drivers/block/blk_legacy.c
Applied to u-boot-dm.

Add a legacy block interface for systemace.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/block/systemace.c | 14 ++++++++++++++ include/blk.h | 1 + 2 files changed, 15 insertions(+)
diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index 09fe834..0d8e26f 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -132,6 +132,13 @@ struct blk_desc *systemace_get_dev(int dev) } #endif
+static int systemace_get_devp(int dev, struct blk_desc **descp) +{ + *descp = systemace_get_dev(dev); + + return 0; +} + /* * This function is called (by dereferencing the block_read pointer in * the dev_desc) to read blocks of data. The return value is the @@ -257,3 +264,10 @@ static unsigned long systemace_read(struct blk_desc *block_dev,
return blkcnt; } + +U_BOOT_LEGACY_BLK(systemace) = { + .if_typename = "ace", + .if_type = IF_TYPE_SYSTEMACE, + .max_devs = 1, + .get_dev = systemace_get_devp, +}; diff --git a/include/blk.h b/include/blk.h index a562c10..2caac9c 100644 --- a/include/blk.h +++ b/include/blk.h @@ -30,6 +30,7 @@ enum if_type { IF_TYPE_SD, IF_TYPE_SATA, IF_TYPE_HOST, + IF_TYPE_SYSTEMACE,
IF_TYPE_COUNT, /* Number of interface types */ };

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Add a legacy block interface for systemace.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/systemace.c | 14 ++++++++++++++ include/blk.h | 1 + 2 files changed, 15 insertions(+)
Applied to u-boot-dm.

Add a legacy block interface for sandbox host.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/block/sandbox.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c index 6d41508..2b6a893 100644 --- a/drivers/block/sandbox.c +++ b/drivers/block/sandbox.c @@ -239,4 +239,11 @@ U_BOOT_DRIVER(sandbox_host_blk) = { .ops = &sandbox_host_blk_ops, .priv_auto_alloc_size = sizeof(struct host_block_dev), }; +#else +U_BOOT_LEGACY_BLK(sandbox_host) = { + .if_typename = "host", + .if_type = IF_TYPE_HOST, + .max_devs = CONFIG_HOST_MAX_DEVICES, + .get_dev = host_get_dev_err, +}; #endif

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Add a legacy block interface for sandbox host.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/sandbox.c | 7 +++++++ 1 file changed, 7 insertions(+)
Applied to u-boot-dm.

Add a legacy block interface for USB storage.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/usb_storage.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/common/usb_storage.c b/common/usb_storage.c index 9285c95..80bf3db 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -1555,4 +1555,11 @@ U_BOOT_DRIVER(usb_storage_blk) = { .id = UCLASS_BLK, .ops = &usb_storage_ops, }; +#else +U_BOOT_LEGACY_BLK(usb) = { + .if_typename = "usb", + .if_type = IF_TYPE_USB, + .max_devs = USB_MAX_STOR_DEV, + .desc = usb_dev_desc, +}; #endif

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Add a legacy block interface for USB storage.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/usb_storage.c | 7 +++++++ 1 file changed, 7 insertions(+)
Applied to u-boot-dm.

Add a legacy block interface for MMC.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/mmc/mmc.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index d3c22ab..024368c 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1582,14 +1582,31 @@ void mmc_destroy(struct mmc *mmc) free(mmc); }
+static int mmc_get_devp(int dev, struct blk_desc **descp) +{ + struct mmc *mmc = find_mmc_device(dev); + int ret; + + if (!mmc) + return -ENODEV; + ret = mmc_init(mmc); + if (ret) + return ret; + + *descp = &mmc->block_dev; + + return 0; +} + #ifdef CONFIG_PARTITIONS struct blk_desc *mmc_get_dev(int dev) { - struct mmc *mmc = find_mmc_device(dev); - if (!mmc || mmc_init(mmc)) + struct blk_desc *desc; + + if (mmc_get_devp(dev, &desc)) return NULL;
- return &mmc->block_dev; + return desc; } #endif
@@ -1965,3 +1982,10 @@ int mmc_set_rst_n_function(struct mmc *mmc, u8 enable) enable); } #endif + +U_BOOT_LEGACY_BLK(mmc) = { + .if_typename = "mmc", + .if_type = IF_TYPE_MMC, + .max_devs = -1, + .get_dev = mmc_get_devp, +};

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Add a legacy block interface for MMC.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/mmc/mmc.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-)
Applied to u-boot-dm.

Now that the MMC code accesses devices by number, we can implement this same interface for driver model, allowing MMC to support using driver model for block devices.
Add the required functions to the uclass.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/block/blk-uclass.c | 280 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 617db22..3687b9a 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -11,6 +11,286 @@ #include <dm/device-internal.h> #include <dm/lists.h>
+static const char *if_typename_str[IF_TYPE_COUNT] = { + [IF_TYPE_IDE] = "ide", + [IF_TYPE_SCSI] = "scsi", + [IF_TYPE_ATAPI] = "atapi", + [IF_TYPE_USB] = "usb", + [IF_TYPE_DOC] = "doc", + [IF_TYPE_MMC] = "mmc", + [IF_TYPE_SD] = "sd", + [IF_TYPE_SATA] = "sata", + [IF_TYPE_HOST] = "host", + [IF_TYPE_SYSTEMACE] = "ace", +}; + +static enum uclass_id if_type_uclass_id[IF_TYPE_COUNT] = { + [IF_TYPE_IDE] = UCLASS_INVALID, + [IF_TYPE_SCSI] = UCLASS_INVALID, + [IF_TYPE_ATAPI] = UCLASS_INVALID, + [IF_TYPE_USB] = UCLASS_MASS_STORAGE, + [IF_TYPE_DOC] = UCLASS_INVALID, + [IF_TYPE_MMC] = UCLASS_MMC, + [IF_TYPE_SD] = UCLASS_INVALID, + [IF_TYPE_SATA] = UCLASS_AHCI, + [IF_TYPE_HOST] = UCLASS_ROOT, + [IF_TYPE_SYSTEMACE] = UCLASS_INVALID, +}; + +static enum if_type if_typename_to_iftype(const char *if_typename) +{ + int i; + + for (i = 0; i < IF_TYPE_COUNT; i++) { + if (if_typename_str[i] && + !strcmp(if_typename, if_typename_str[i])) + return i; + } + + return IF_TYPE_UNKNOWN; +} + +static enum uclass_id if_type_to_uclass_id(enum if_type if_type) +{ + return if_type_uclass_id[if_type]; +} + +struct blk_desc *blk_get_devnum_by_type(enum if_type if_type, int devnum) +{ + struct blk_desc *desc; + struct udevice *dev; + int ret; + + ret = blk_get_device(if_type, devnum, &dev); + if (ret) + return NULL; + desc = dev_get_uclass_platdata(dev); + + return desc; +} + +/* + * This function is complicated with driver model. We look up the interface + * name in a local table. This gives us an interface type which we can match + * against the uclass of the block device's parent. + */ +struct blk_desc *blk_get_devnum_by_typename(const char *if_typename, int devnum) +{ + enum uclass_id uclass_id; + enum if_type if_type; + struct udevice *dev; + struct uclass *uc; + int ret; + + if_type = if_typename_to_iftype(if_typename); + if (if_type == IF_TYPE_UNKNOWN) { + debug("%s: Unknown interface type '%s'\n", __func__, + if_typename); + return NULL; + } + uclass_id = if_type_to_uclass_id(if_type); + if (uclass_id == UCLASS_INVALID) { + debug("%s: Unknown uclass for interface type'\n", + if_typename_str[if_type]); + return NULL; + } + + ret = uclass_get(UCLASS_BLK, &uc); + if (ret) + return NULL; + uclass_foreach_dev(dev, uc) { + struct blk_desc *desc = dev_get_uclass_platdata(dev); + + debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, + if_type, devnum, dev->name, desc->if_type, desc->devnum); + if (desc->devnum != devnum) + continue; + + /* Find out the parent device uclass */ + if (device_get_uclass_id(dev->parent) != uclass_id) { + debug("%s: parent uclass %d, this dev %d\n", __func__, + device_get_uclass_id(dev->parent), uclass_id); + continue; + } + + if (device_probe(dev)) + return NULL; + + debug("%s: Device desc %p\n", __func__, desc); + return desc; + } + debug("%s: No device found\n", __func__); + + return NULL; +} + +/** + * get_desc() - Get the block device descriptor for the given device number + * + * @if_type: Interface type + * @devnum: Device number (0 = first) + * @descp: Returns block device descriptor on success + * @return 0 on success, -ENODEV if there is no such device and no device + * with a higher device number, -ENOENT if there is no such device but there + * is one with a higher number, or other -ve on other error. + */ +static int get_desc(enum if_type if_type, int devnum, struct blk_desc **descp) +{ + bool found_more = false; + struct udevice *dev; + struct uclass *uc; + int ret; + + *descp = NULL; + ret = uclass_get(UCLASS_BLK, &uc); + if (ret) + return ret; + uclass_foreach_dev(dev, uc) { + struct blk_desc *desc = dev_get_uclass_platdata(dev); + + debug("%s: if_type=%d, devnum=%d: %s, %d, %d\n", __func__, + if_type, devnum, dev->name, desc->if_type, desc->devnum); + if (desc->if_type == if_type) { + if (desc->devnum == devnum) { + ret = device_probe(dev); + if (ret) + return ret; + + } else if (desc->devnum > devnum) { + found_more = true; + } + } + } + + return found_more ? -ENOENT : -ENODEV; +} + +int blk_list_part(enum if_type if_type) +{ + struct blk_desc *desc; + int devnum, ok; + int ret; + + for (ok = 0, devnum = 0;; ++devnum) { + ret = get_desc(if_type, devnum, &desc); + if (ret == -ENODEV) + break; + else if (ret) + continue; + if (desc->part_type != PART_TYPE_UNKNOWN) { + ++ok; + if (devnum) + putc('\n'); + part_print(desc); + } + } + if (!ok) + return -ENODEV; + + return 0; +} + +int blk_print_part_devnum(enum if_type if_type, int devnum) +{ + struct blk_desc *desc; + int ret; + + ret = get_desc(if_type, devnum, &desc); + if (ret) + return ret; + if (desc->type == DEV_TYPE_UNKNOWN) + return -ENOENT; + part_print(desc); + + return 0; +} + +void blk_list_devices(enum if_type if_type) +{ + struct blk_desc *desc; + int ret; + int i; + + for (i = 0;; ++i) { + ret = get_desc(if_type, i, &desc); + if (ret == -ENODEV) + break; + else if (ret) + continue; + if (desc->type == DEV_TYPE_UNKNOWN) + continue; /* list only known devices */ + printf("Device %d: ", i); + dev_print(desc); + } +} + +int blk_print_device_num(enum if_type if_type, int devnum) +{ + struct blk_desc *desc; + int ret; + + ret = get_desc(if_type, devnum, &desc); + if (ret) + return ret; + printf("\nIDE device %d: ", devnum); + dev_print(desc); + + return 0; +} + +int blk_show_device(enum if_type if_type, int devnum) +{ + struct blk_desc *desc; + int ret; + + printf("\nDevice %d: ", devnum); + ret = get_desc(if_type, devnum, &desc); + if (ret == -ENODEV || ret == -ENOENT) { + printf("unknown device\n"); + return -ENODEV; + } + if (ret) + return ret; + dev_print(desc); + + if (desc->type == DEV_TYPE_UNKNOWN) + return -ENOENT; + + return 0; +} + +ulong blk_read_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, void *buffer) +{ + struct blk_desc *desc; + ulong n; + int ret; + + ret = get_desc(if_type, devnum, &desc); + if (ret) + return ret; + n = blk_dread(desc, start, blkcnt, buffer); + if (IS_ERR_VALUE(n)) + return n; + + /* flush cache after read */ + flush_cache((ulong)buffer, blkcnt * desc->blksz); + + return n; +} + +ulong blk_write_devnum(enum if_type if_type, int devnum, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + struct blk_desc *desc; + int ret; + + ret = get_desc(if_type, devnum, &desc); + if (ret) + return ret; + return blk_dwrite(desc, start, blkcnt, buffer); +} + int blk_first_device(int if_type, struct udevice **devp) { struct blk_desc *desc;

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Now that the MMC code accesses devices by number, we can implement this same interface for driver model, allowing MMC to support using driver model for block devices.
Add the required functions to the uclass.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/blk-uclass.c | 280 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 280 insertions(+)
Applied to u-boot-dm.

At present the SCSI command code includes both the command-processing code and the core SCSI functions and data structures.
Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly. This functions use the new legacy block functions.
With this commit: - There is no CONFIG option referenced from the command code - The concept of a 'current SCSI device' is confined to the command code
This will make it easier to convert this code to driver model.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
cmd/Makefile | 6 - cmd/scsi.c | 626 +++----------------------------------------------------- common/Makefile | 4 + common/scsi.c | 567 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 600 insertions(+), 603 deletions(-) create mode 100644 common/scsi.c
diff --git a/cmd/Makefile b/cmd/Makefile index 6612a3b..e3e0c74 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -155,12 +155,6 @@ obj-$(CONFIG_CMD_PMIC) += pmic.o obj-$(CONFIG_CMD_REGULATOR) += regulator.o endif # !CONFIG_SPL_BUILD
-ifdef CONFIG_SPL_BUILD -ifdef CONFIG_SPL_SATA_SUPPORT -obj-$(CONFIG_SCSI) += scsi.o -endif -endif # CONFIG_SPL_BUILD - obj-$(CONFIG_CMD_BLOB) += blob.o
# core command diff --git a/cmd/scsi.c b/cmd/scsi.c index 751fc58..387ca1a 100644 --- a/cmd/scsi.c +++ b/cmd/scsi.c @@ -10,355 +10,27 @@ */ #include <common.h> #include <command.h> -#include <inttypes.h> -#include <asm/processor.h> #include <scsi.h> -#include <image.h> -#include <pci.h> - -#ifdef CONFIG_SCSI_DEV_LIST -#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST -#else -#ifdef CONFIG_SCSI_SYM53C8XX -#define SCSI_VEND_ID 0x1000 -#ifndef CONFIG_SCSI_DEV_ID -#define SCSI_DEV_ID 0x0001 -#else -#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID -#endif -#elif defined CONFIG_SATA_ULI5288 - -#define SCSI_VEND_ID 0x10b9 -#define SCSI_DEV_ID 0x5288 - -#elif !defined(CONFIG_SCSI_AHCI_PLAT) -#error no scsi device defined -#endif -#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID} -#endif - -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) -const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST }; -#endif -static ccb tempccb; /* temporary scsi command buffer */ - -static unsigned char tempbuff[512]; /* temporary data buffer */ - -static int scsi_max_devs; /* number of highest available scsi device */
static int scsi_curr_dev; /* current device */
-static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; - -/* almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_READ_BLK 0xFFFF -#define SCSI_LBA48_READ 0xFFFFFFF - -#ifdef CONFIG_SYS_64BIT_LBA -void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks) -{ - pccb->cmd[0] = SCSI_READ16; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff; - pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff; - pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff; - pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff; - pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff; - pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff; - pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[9] = (unsigned char)start & 0xff; - pccb->cmd[10] = 0; - pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff; - pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff; - pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff; - pccb->cmd[14] = (unsigned char)blocks & 0xff; - pccb->cmd[15] = 0; - pccb->cmdlen = 16; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], - pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], - pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); -} -#endif - -void scsi_setup_read_ext(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_READ10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; - pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; - pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[5] = (unsigned char)start & 0xff; - pccb->cmd[6] = 0; - pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff; - pccb->cmd[8] = (unsigned char)blocks & 0xff; - pccb->cmd[6] = 0; - pccb->cmdlen=10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug ("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", - pccb->cmd[0],pccb->cmd[1], - pccb->cmd[2],pccb->cmd[3],pccb->cmd[4],pccb->cmd[5], - pccb->cmd[7],pccb->cmd[8]); -} - -void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_WRITE10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; - pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; - pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[5] = (unsigned char)start & 0xff; - pccb->cmd[6] = 0; - pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff; - pccb->cmd[8] = (unsigned char)blocks & 0xff; - pccb->cmd[9] = 0; - pccb->cmdlen = 10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - 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]); -} - -void scsi_setup_read6(ccb * pccb, lbaint_t start, unsigned short blocks) -{ - pccb->cmd[0] = SCSI_READ6; - pccb->cmd[1] = pccb->lun << 5 | ((unsigned char)(start >> 16) & 0x1f); - pccb->cmd[2] = (unsigned char)(start >> 8) & 0xff; - pccb->cmd[3] = (unsigned char)start & 0xff; - pccb->cmd[4] = (unsigned char)blocks & 0xff; - pccb->cmd[5] = 0; - pccb->cmdlen=6; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - debug("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", - pccb->cmd[0], pccb->cmd[1], - pccb->cmd[2], pccb->cmd[3], pccb->cmd[4]); -} - - -void scsi_setup_inquiry(ccb * pccb) -{ - pccb->cmd[0] = SCSI_INQUIRY; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = 0; - pccb->cmd[3] = 0; - if (pccb->datalen > 255) - pccb->cmd[4] = 255; - else - pccb->cmd[4] = (unsigned char)pccb->datalen; - pccb->cmd[5] = 0; - pccb->cmdlen=6; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ -} - -static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks = 0; - ccb* pccb=(ccb *)&tempccb; - device&=0xff; - - /* Setup device */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; - buf_addr = (unsigned long)buffer; - start = blknr; - blks = blkcnt; - debug("\nscsi_read: dev %d startblk " LBAF - ", blccnt " LBAF " buffer %lx\n", - device, start, blks, (unsigned long)buffer); - do { - pccb->pdata = (unsigned char *)buf_addr; -#ifdef CONFIG_SYS_64BIT_LBA - if (start > SCSI_LBA48_READ) { - unsigned long blocks; - blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); - pccb->datalen = scsi_dev_desc[device].blksz * blocks; - scsi_setup_read16(pccb, start, blocks); - start += blocks; - blks -= blocks; - } else -#endif - if (blks > SCSI_MAX_READ_BLK) { - pccb->datalen = scsi_dev_desc[device].blksz * - SCSI_MAX_READ_BLK; - smallblks = SCSI_MAX_READ_BLK; - scsi_setup_read_ext(pccb, start, smallblks); - start += SCSI_MAX_READ_BLK; - blks -= SCSI_MAX_READ_BLK; - } - else { - pccb->datalen = scsi_dev_desc[device].blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_read_ext(pccb, start, smallblks); - start += blks; - blks=0; - } - debug("scsi_read_ext: startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", - start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt -= blks; - break; - } - buf_addr+=pccb->datalen; - } while (blks != 0); - debug("scsi_read_ext: end startblk " LBAF - ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); - return blkcnt; -} - -/******************************************************************************* - * scsi_write - */ - -/* Almost the maximum amount of the scsi_ext command.. */ -#define SCSI_MAX_WRITE_BLK 0xFFFF - -static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, - lbaint_t blkcnt, const void *buffer) -{ - int device = block_dev->devnum; - lbaint_t start, blks; - uintptr_t buf_addr; - unsigned short smallblks; - ccb* pccb = (ccb *)&tempccb; - device &= 0xff; - /* Setup device - */ - pccb->target = scsi_dev_desc[device].target; - pccb->lun = scsi_dev_desc[device].lun; - buf_addr = (unsigned long)buffer; - start = blknr; - blks = blkcnt; - debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", - __func__, device, start, blks, (unsigned long)buffer); - do { - pccb->pdata = (unsigned char *)buf_addr; - if (blks > SCSI_MAX_WRITE_BLK) { - pccb->datalen = (scsi_dev_desc[device].blksz * - SCSI_MAX_WRITE_BLK); - smallblks = SCSI_MAX_WRITE_BLK; - scsi_setup_write_ext(pccb, start, smallblks); - start += SCSI_MAX_WRITE_BLK; - blks -= SCSI_MAX_WRITE_BLK; - } else { - pccb->datalen = scsi_dev_desc[device].blksz * blks; - smallblks = (unsigned short)blks; - scsi_setup_write_ext(pccb, start, smallblks); - start += blks; - blks = 0; - } - debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - if (scsi_exec(pccb) != true) { - scsi_print_error(pccb); - blkcnt -= blks; - break; - } - buf_addr += pccb->datalen; - } while (blks != 0); - debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", - __func__, start, smallblks, buf_addr); - return blkcnt; -} - -int scsi_get_disk_count(void) -{ - return scsi_max_devs; -} - -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) -void scsi_init(void) -{ - int busdevfunc = -1; - int i; - /* - * Find a device from the list, this driver will support a single - * controller. - */ - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { - /* get PCI Device ID */ -#ifdef CONFIG_DM_PCI - struct udevice *dev; - int ret; - - ret = dm_pci_find_device(scsi_device_list[i].vendor, - scsi_device_list[i].device, 0, &dev); - if (!ret) { - busdevfunc = dm_pci_get_bdf(dev); - break; - } -#else - busdevfunc = pci_find_device(scsi_device_list[i].vendor, - scsi_device_list[i].device, - 0); -#endif - if (busdevfunc != -1) - break; - } - - if (busdevfunc == -1) { - printf("Error: SCSI Controller(s) "); - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { - printf("%04X:%04X ", - scsi_device_list[i].vendor, - scsi_device_list[i].device); - } - printf("not found\n"); - return; - } -#ifdef DEBUG - else { - printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n", - scsi_device_list[i].vendor, - scsi_device_list[i].device, - (busdevfunc >> 16) & 0xFF, - (busdevfunc >> 11) & 0x1F, - (busdevfunc >> 8) & 0x7); - } -#endif - bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci"); - scsi_low_level_init(busdevfunc); - scsi_scan(1); - bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI); -} -#endif - -#ifdef CONFIG_PARTITIONS -struct blk_desc *scsi_get_dev(int dev) -{ - return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL; -} -#endif - -#ifndef CONFIG_SPL_BUILD -/****************************************************************************** +/* * scsi boot command intepreter. Derived from diskboot */ -int do_scsiboot (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int do_scsiboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { return common_diskboot(cmdtp, "scsi", argc, argv); }
-/********************************************************************************* +/* * scsi command intepreter */ -int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int do_scsi(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { switch (argc) { case 0: case 1: return CMD_RET_USAGE; - case 2: if (strncmp(argv[1], "res", 3) == 0) { printf("\nReset SCSI\n"); @@ -367,23 +39,15 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } if (strncmp(argv[1], "inf", 3) == 0) { - int i; - for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; ++i) { - if (scsi_dev_desc[i].type == DEV_TYPE_UNKNOWN) - continue; /* list only known devices */ - printf("SCSI dev. %d: ", i); - dev_print(&scsi_dev_desc[i]); - } + blk_list_devices(IF_TYPE_SCSI); return 0; } if (strncmp(argv[1], "dev", 3) == 0) { - if (scsi_curr_dev < 0 || - scsi_curr_dev >= CONFIG_SYS_SCSI_MAX_DEVICE) { + if (blk_print_device_num(IF_TYPE_SCSI, scsi_curr_dev)) { printf("\nno SCSI devices available\n"); - return 1; + return CMD_RET_FAILURE; } - printf("\n Device %d: ", scsi_curr_dev); - dev_print(&scsi_dev_desc[scsi_curr_dev]); + return 0; } if (strncmp(argv[1], "scan", 4) == 0) { @@ -391,46 +55,32 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } if (strncmp(argv[1], "part", 4) == 0) { - int dev, ok; - for (ok = 0, dev = 0; - dev < CONFIG_SYS_SCSI_MAX_DEVICE; ++dev) { - if (scsi_dev_desc[dev].type != - DEV_TYPE_UNKNOWN) { - ok++; - if (dev) - printf("\n"); - debug("print_part of %x\n", dev); - part_print(&scsi_dev_desc[dev]); - } - } - if (!ok) + if (blk_list_part(IF_TYPE_SCSI)) printf("\nno SCSI devices available\n"); - return 1; + return 0; } return CMD_RET_USAGE; case 3: if (strncmp(argv[1], "dev", 3) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10); - printf("\nSCSI device %d: ", dev); - if (dev >= CONFIG_SYS_SCSI_MAX_DEVICE) { - printf("unknown device\n"); - return 1; + + if (!blk_show_device(IF_TYPE_SCSI, dev)) { + scsi_curr_dev = dev; + printf("... is now current device\n"); + } else { + return CMD_RET_FAILURE; } - printf("\n Device %d: ", dev); - dev_print(&scsi_dev_desc[dev]); - if (scsi_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; - scsi_curr_dev = dev; - printf("... is now current device\n"); return 0; } if (strncmp(argv[1], "part", 4) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10); - if (scsi_dev_desc[dev].type != DEV_TYPE_UNKNOWN) - part_print(&scsi_dev_desc[dev]); - else - printf("\nSCSI device %d not available\n", dev); - return 1; + + if (blk_print_part_devnum(IF_TYPE_SCSI, dev)) { + printf("\nSCSI device %d not available\n", + dev); + return CMD_RET_FAILURE; + } + return 0; } return CMD_RET_USAGE; default: @@ -440,10 +90,11 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ulong blk = simple_strtoul(argv[3], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; + printf("\nSCSI read: device %d block # %ld, count %ld ... ", scsi_curr_dev, blk, cnt); - n = scsi_read(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); + n = blk_read_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk, + cnt, (ulong *)addr); printf("%ld blocks read: %s\n", n, n == cnt ? "OK" : "ERROR"); return 0; @@ -452,10 +103,11 @@ int do_scsi (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ulong blk = simple_strtoul(argv[3], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); ulong n; + printf("\nSCSI write: device %d block # %ld, count %ld ... ", scsi_curr_dev, blk, cnt); - n = scsi_write(&scsi_dev_desc[scsi_curr_dev], - blk, cnt, (ulong *)addr); + n = blk_write_devnum(IF_TYPE_SCSI, scsi_curr_dev, blk, + cnt, (ulong *)addr); printf("%ld blocks written: %s\n", n, n == cnt ? "OK" : "ERROR"); return 0; @@ -483,223 +135,3 @@ U_BOOT_CMD( "boot from SCSI device", "loadAddr dev:part" ); -#endif - -/* copy src to dest, skipping leading and trailing blanks - * and null terminate the string - */ -void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len) -{ - int start,end; - - start = 0; - while (start < len) { - if (src[start] != ' ') - break; - start++; - } - end = len-1; - while (end > start) { - if (src[end] != ' ') - break; - end--; - } - for (; start <= end; start++) - *dest ++= src[start]; - *dest='\0'; -} - - -/* Trim trailing blanks, and NUL-terminate string - */ -void scsi_trim_trail (unsigned char *str, unsigned int len) -{ - unsigned char *p = str + len - 1; - - while (len-- > 0) { - *p-- = '\0'; - if (*p != ' ') { - return; - } - } -} - -int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) -{ - *capacity = 0; - - memset(pccb->cmd, '\0', sizeof(pccb->cmd)); - pccb->cmd[0] = SCSI_RD_CAPAC10; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmdlen = 10; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - - pccb->datalen = 8; - if (scsi_exec(pccb) != true) - return 1; - - *capacity = ((lbaint_t)pccb->pdata[0] << 24) | - ((lbaint_t)pccb->pdata[1] << 16) | - ((lbaint_t)pccb->pdata[2] << 8) | - ((lbaint_t)pccb->pdata[3]); - - if (*capacity != 0xffffffff) { - /* Read capacity (10) was sufficient for this drive. */ - *blksz = ((unsigned long)pccb->pdata[4] << 24) | - ((unsigned long)pccb->pdata[5] << 16) | - ((unsigned long)pccb->pdata[6] << 8) | - ((unsigned long)pccb->pdata[7]); - return 0; - } - - /* Read capacity (10) was insufficient. Use read capacity (16). */ - memset(pccb->cmd, '\0', sizeof(pccb->cmd)); - pccb->cmd[0] = SCSI_RD_CAPAC16; - pccb->cmd[1] = 0x10; - pccb->cmdlen = 16; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ - - pccb->datalen = 16; - if (scsi_exec(pccb) != true) - return 1; - - *capacity = ((uint64_t)pccb->pdata[0] << 56) | - ((uint64_t)pccb->pdata[1] << 48) | - ((uint64_t)pccb->pdata[2] << 40) | - ((uint64_t)pccb->pdata[3] << 32) | - ((uint64_t)pccb->pdata[4] << 24) | - ((uint64_t)pccb->pdata[5] << 16) | - ((uint64_t)pccb->pdata[6] << 8) | - ((uint64_t)pccb->pdata[7]); - - *blksz = ((uint64_t)pccb->pdata[8] << 56) | - ((uint64_t)pccb->pdata[9] << 48) | - ((uint64_t)pccb->pdata[10] << 40) | - ((uint64_t)pccb->pdata[11] << 32) | - ((uint64_t)pccb->pdata[12] << 24) | - ((uint64_t)pccb->pdata[13] << 16) | - ((uint64_t)pccb->pdata[14] << 8) | - ((uint64_t)pccb->pdata[15]); - - return 0; -} - - -/************************************************************************************ - * Some setup (fill-in) routines - */ -void scsi_setup_test_unit_ready(ccb * pccb) -{ - pccb->cmd[0] = SCSI_TST_U_RDY; - pccb->cmd[1] = pccb->lun << 5; - pccb->cmd[2] = 0; - pccb->cmd[3] = 0; - pccb->cmd[4] = 0; - pccb->cmd[5] = 0; - pccb->cmdlen = 6; - pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ -} - -/********************************************************************************* - * (re)-scan the scsi bus and reports scsi device info - * to the user if mode = 1 - */ -void scsi_scan(int mode) -{ - unsigned char i,perq,modi,lun; - lbaint_t capacity; - unsigned long blksz; - ccb* pccb=(ccb *)&tempccb; - - if (mode == 1) - printf("scanning bus for devices...\n"); - for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++) { - scsi_dev_desc[i].target = 0xff; - scsi_dev_desc[i].lun = 0xff; - scsi_dev_desc[i].lba = 0; - scsi_dev_desc[i].blksz = 0; - scsi_dev_desc[i].log2blksz = - LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); - scsi_dev_desc[i].type = DEV_TYPE_UNKNOWN; - scsi_dev_desc[i].vendor[0] = 0; - scsi_dev_desc[i].product[0] = 0; - scsi_dev_desc[i].revision[0] = 0; - scsi_dev_desc[i].removable = false; - scsi_dev_desc[i].if_type = IF_TYPE_SCSI; - scsi_dev_desc[i].devnum = i; - scsi_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - scsi_dev_desc[i].block_read = scsi_read; - scsi_dev_desc[i].block_write = scsi_write; - } - scsi_max_devs = 0; - for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { - pccb->target = i; - for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) { - pccb->lun = lun; - pccb->pdata = (unsigned char *)&tempbuff; - pccb->datalen = 512; - scsi_setup_inquiry(pccb); - if (scsi_exec(pccb) != true) { - if(pccb->contr_stat==SCSI_SEL_TIME_OUT) { - debug("Selection timeout ID %d\n", - pccb->target); - continue; /* selection timeout => assuming no device present */ - } - scsi_print_error(pccb); - continue; - } - perq = tempbuff[0]; - modi = tempbuff[1]; - if ((perq & 0x1f) == 0x1f) - continue; /* skip unknown devices */ - if ((modi & 0x80) == 0x80) /* drive is removable */ - scsi_dev_desc[scsi_max_devs].removable = true; - /* get info for this device */ - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].vendor[0], - &tempbuff[8], 8); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].product[0], - &tempbuff[16], 16); - scsi_ident_cpy((unsigned char *)&scsi_dev_desc[scsi_max_devs].revision[0], - &tempbuff[32], 4); - scsi_dev_desc[scsi_max_devs].target = pccb->target; - scsi_dev_desc[scsi_max_devs].lun = pccb->lun; - - pccb->datalen = 0; - scsi_setup_test_unit_ready(pccb); - if (scsi_exec(pccb) != true) { - if (scsi_dev_desc[scsi_max_devs].removable) { - scsi_dev_desc[scsi_max_devs].type = - perq; - goto removable; - } - scsi_print_error(pccb); - continue; - } - if (scsi_read_capacity(pccb, &capacity, &blksz)) { - scsi_print_error(pccb); - continue; - } - scsi_dev_desc[scsi_max_devs].lba = capacity; - scsi_dev_desc[scsi_max_devs].blksz = blksz; - scsi_dev_desc[scsi_max_devs].log2blksz = - LOG2(scsi_dev_desc[scsi_max_devs].blksz); - scsi_dev_desc[scsi_max_devs].type = perq; - part_init(&scsi_dev_desc[scsi_max_devs]); -removable: - if(mode==1) { - printf (" Device %d: ", scsi_max_devs); - dev_print(&scsi_dev_desc[scsi_max_devs]); - } /* if mode */ - scsi_max_devs++; - } /* next LUN */ - } - if (scsi_max_devs > 0) - scsi_curr_dev = 0; - else - scsi_curr_dev = -1; - - printf("Found %d device(s).\n", scsi_max_devs); -#ifndef CONFIG_SPL_BUILD - setenv_ulong("scsidevs", scsi_max_devs); -#endif -} diff --git a/common/Makefile b/common/Makefile index b23f312..397df61 100644 --- a/common/Makefile +++ b/common/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o obj-$(CONFIG_LYNXKDI) += lynxkdi.o obj-$(CONFIG_MENU) += menu.o +obj-$(CONFIG_SCSI) += scsi.o obj-$(CONFIG_UPDATE_TFTP) += update.o obj-$(CONFIG_DFU_TFTP) += update.o obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o @@ -112,6 +113,9 @@ obj-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o obj-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o obj-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o endif +ifdef CONFIG_SPL_SATA_SUPPORT +obj-$(CONFIG_SCSI) += scsi.o +endif endif #environment obj-y += env_common.o diff --git a/common/scsi.c b/common/scsi.c new file mode 100644 index 0000000..a336a10 --- /dev/null +++ b/common/scsi.c @@ -0,0 +1,567 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <inttypes.h> +#include <pci.h> +#include <scsi.h> + +#ifdef CONFIG_SCSI_DEV_LIST +#define SCSI_DEV_LIST CONFIG_SCSI_DEV_LIST +#else +#ifdef CONFIG_SCSI_SYM53C8XX +#define SCSI_VEND_ID 0x1000 +#ifndef CONFIG_SCSI_DEV_ID +#define SCSI_DEV_ID 0x0001 +#else +#define SCSI_DEV_ID CONFIG_SCSI_DEV_ID +#endif +#elif defined CONFIG_SATA_ULI5288 + +#define SCSI_VEND_ID 0x10b9 +#define SCSI_DEV_ID 0x5288 + +#elif !defined(CONFIG_SCSI_AHCI_PLAT) +#error no scsi device defined +#endif +#define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID} +#endif + +#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) +const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST }; +#endif +static ccb tempccb; /* temporary scsi command buffer */ + +static unsigned char tempbuff[512]; /* temporary data buffer */ + +static int scsi_max_devs; /* number of highest available scsi device */ + +static int scsi_curr_dev; /* current device */ + +static struct blk_desc scsi_dev_desc[CONFIG_SYS_SCSI_MAX_DEVICE]; + +/* almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_READ_BLK 0xFFFF +#define SCSI_LBA48_READ 0xFFFFFFF + +#ifdef CONFIG_SYS_64BIT_LBA +void scsi_setup_read16(ccb *pccb, lbaint_t start, unsigned long blocks) +{ + pccb->cmd[0] = SCSI_READ16; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 56) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 48) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 40) & 0xff; + pccb->cmd[5] = (unsigned char)(start >> 32) & 0xff; + pccb->cmd[6] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[7] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[8] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[9] = (unsigned char)start & 0xff; + pccb->cmd[10] = 0; + pccb->cmd[11] = (unsigned char)(blocks >> 24) & 0xff; + pccb->cmd[12] = (unsigned char)(blocks >> 16) & 0xff; + pccb->cmd[13] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[14] = (unsigned char)blocks & 0xff; + pccb->cmd[15] = 0; + pccb->cmdlen = 16; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("scsi_setup_read16: cmd: %02X %02X startblk %02X%02X%02X%02X%02X%02X%02X%02X blccnt %02X%02X%02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[6], pccb->cmd[7], pccb->cmd[8], pccb->cmd[9], + pccb->cmd[11], pccb->cmd[12], pccb->cmd[13], pccb->cmd[14]); +} +#endif + +void scsi_setup_read_ext(ccb *pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0] = SCSI_READ10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = (unsigned char)(blocks >> 8) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[6] = 0; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("scsi_setup_read_ext: cmd: %02X %02X startblk %02X%02X%02X%02X blccnt %02X%02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4], pccb->cmd[5], + pccb->cmd[7], pccb->cmd[8]); +} + +void scsi_setup_write_ext(ccb *pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0] = SCSI_WRITE10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = (unsigned char)(start >> 24) & 0xff; + pccb->cmd[3] = (unsigned char)(start >> 16) & 0xff; + pccb->cmd[4] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[5] = (unsigned char)start & 0xff; + pccb->cmd[6] = 0; + pccb->cmd[7] = ((unsigned char)(blocks >> 8)) & 0xff; + pccb->cmd[8] = (unsigned char)blocks & 0xff; + pccb->cmd[9] = 0; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + 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]); +} + +void scsi_setup_read6(ccb *pccb, lbaint_t start, unsigned short blocks) +{ + pccb->cmd[0] = SCSI_READ6; + pccb->cmd[1] = pccb->lun << 5 | ((unsigned char)(start >> 16) & 0x1f); + pccb->cmd[2] = (unsigned char)(start >> 8) & 0xff; + pccb->cmd[3] = (unsigned char)start & 0xff; + pccb->cmd[4] = (unsigned char)blocks & 0xff; + pccb->cmd[5] = 0; + pccb->cmdlen = 6; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + debug("scsi_setup_read6: cmd: %02X %02X startblk %02X%02X blccnt %02X\n", + pccb->cmd[0], pccb->cmd[1], + pccb->cmd[2], pccb->cmd[3], pccb->cmd[4]); +} + + +void scsi_setup_inquiry(ccb *pccb) +{ + pccb->cmd[0] = SCSI_INQUIRY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + if (pccb->datalen > 255) + pccb->cmd[4] = 255; + else + pccb->cmd[4] = (unsigned char)pccb->datalen; + pccb->cmd[5] = 0; + pccb->cmdlen = 6; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ +} + +static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, void *buffer) +{ + int device = block_dev->devnum; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks = 0; + ccb *pccb = (ccb *)&tempccb; + device &= 0xff; + + /* Setup device */ + pccb->target = scsi_dev_desc[device].target; + pccb->lun = scsi_dev_desc[device].lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; + debug("\nscsi_read: dev %d startblk " LBAF + ", blccnt " LBAF " buffer %lx\n", + device, start, blks, (unsigned long)buffer); + do { + pccb->pdata = (unsigned char *)buf_addr; +#ifdef CONFIG_SYS_64BIT_LBA + if (start > SCSI_LBA48_READ) { + unsigned long blocks; + blocks = min_t(lbaint_t, blks, SCSI_MAX_READ_BLK); + pccb->datalen = scsi_dev_desc[device].blksz * blocks; + scsi_setup_read16(pccb, start, blocks); + start += blocks; + blks -= blocks; + } else +#endif + if (blks > SCSI_MAX_READ_BLK) { + pccb->datalen = scsi_dev_desc[device].blksz * + SCSI_MAX_READ_BLK; + smallblks = SCSI_MAX_READ_BLK; + scsi_setup_read_ext(pccb, start, smallblks); + start += SCSI_MAX_READ_BLK; + blks -= SCSI_MAX_READ_BLK; + } else { + pccb->datalen = scsi_dev_desc[device].blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_read_ext(pccb, start, smallblks); + start += blks; + blks = 0; + } + debug("scsi_read_ext: startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", + start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt -= blks; + break; + } + buf_addr += pccb->datalen; + } while (blks != 0); + debug("scsi_read_ext: end startblk " LBAF + ", blccnt %x buffer %" PRIXPTR "\n", start, smallblks, buf_addr); + return blkcnt; +} + +/******************************************************************************* + * scsi_write + */ + +/* Almost the maximum amount of the scsi_ext command.. */ +#define SCSI_MAX_WRITE_BLK 0xFFFF + +static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, + lbaint_t blkcnt, const void *buffer) +{ + int device = block_dev->devnum; + lbaint_t start, blks; + uintptr_t buf_addr; + unsigned short smallblks; + ccb *pccb = (ccb *)&tempccb; + + device &= 0xff; + + /* Setup device */ + pccb->target = scsi_dev_desc[device].target; + pccb->lun = scsi_dev_desc[device].lun; + buf_addr = (unsigned long)buffer; + start = blknr; + blks = blkcnt; + debug("\n%s: dev %d startblk " LBAF ", blccnt " LBAF " buffer %lx\n", + __func__, device, start, blks, (unsigned long)buffer); + do { + pccb->pdata = (unsigned char *)buf_addr; + if (blks > SCSI_MAX_WRITE_BLK) { + pccb->datalen = (scsi_dev_desc[device].blksz * + SCSI_MAX_WRITE_BLK); + smallblks = SCSI_MAX_WRITE_BLK; + scsi_setup_write_ext(pccb, start, smallblks); + start += SCSI_MAX_WRITE_BLK; + blks -= SCSI_MAX_WRITE_BLK; + } else { + pccb->datalen = scsi_dev_desc[device].blksz * blks; + smallblks = (unsigned short)blks; + scsi_setup_write_ext(pccb, start, smallblks); + start += blks; + blks = 0; + } + debug("%s: startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + if (scsi_exec(pccb) != true) { + scsi_print_error(pccb); + blkcnt -= blks; + break; + } + buf_addr += pccb->datalen; + } while (blks != 0); + debug("%s: end startblk " LBAF ", blccnt %x buffer %" PRIXPTR "\n", + __func__, start, smallblks, buf_addr); + return blkcnt; +} + +int scsi_get_disk_count(void) +{ + return scsi_max_devs; +} + +#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) +void scsi_init(void) +{ + int busdevfunc = -1; + int i; + /* + * Find a device from the list, this driver will support a single + * controller. + */ + for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { + /* get PCI Device ID */ +#ifdef CONFIG_DM_PCI + struct udevice *dev; + int ret; + + ret = dm_pci_find_device(scsi_device_list[i].vendor, + scsi_device_list[i].device, 0, &dev); + if (!ret) { + busdevfunc = dm_pci_get_bdf(dev); + break; + } +#else + busdevfunc = pci_find_device(scsi_device_list[i].vendor, + scsi_device_list[i].device, + 0); +#endif + if (busdevfunc != -1) + break; + } + + if (busdevfunc == -1) { + printf("Error: SCSI Controller(s) "); + for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { + printf("%04X:%04X ", + scsi_device_list[i].vendor, + scsi_device_list[i].device); + } + printf("not found\n"); + return; + } +#ifdef DEBUG + else { + printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n", + scsi_device_list[i].vendor, + scsi_device_list[i].device, + (busdevfunc >> 16) & 0xFF, + (busdevfunc >> 11) & 0x1F, + (busdevfunc >> 8) & 0x7); + } +#endif + bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci"); + scsi_low_level_init(busdevfunc); + scsi_scan(1); + bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI); +} +#endif + +#ifdef CONFIG_PARTITIONS +struct blk_desc *scsi_get_dev(int dev) +{ + return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL; +} +#endif + +/* copy src to dest, skipping leading and trailing blanks + * and null terminate the string + */ +void scsi_ident_cpy(unsigned char *dest, unsigned char *src, unsigned int len) +{ + int start, end; + + start = 0; + while (start < len) { + if (src[start] != ' ') + break; + start++; + } + end = len-1; + while (end > start) { + if (src[end] != ' ') + break; + end--; + } + for (; start <= end; start++) + *dest ++= src[start]; + *dest = '\0'; +} + + +/* Trim trailing blanks, and NUL-terminate string + */ +void scsi_trim_trail(unsigned char *str, unsigned int len) +{ + unsigned char *p = str + len - 1; + + while (len-- > 0) { + *p-- = '\0'; + if (*p != ' ') + return; + } +} + +int scsi_read_capacity(ccb *pccb, lbaint_t *capacity, unsigned long *blksz) +{ + *capacity = 0; + + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); + pccb->cmd[0] = SCSI_RD_CAPAC10; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmdlen = 10; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + + pccb->datalen = 8; + if (scsi_exec(pccb) != true) + return 1; + + *capacity = ((lbaint_t)pccb->pdata[0] << 24) | + ((lbaint_t)pccb->pdata[1] << 16) | + ((lbaint_t)pccb->pdata[2] << 8) | + ((lbaint_t)pccb->pdata[3]); + + if (*capacity != 0xffffffff) { + /* Read capacity (10) was sufficient for this drive. */ + *blksz = ((unsigned long)pccb->pdata[4] << 24) | + ((unsigned long)pccb->pdata[5] << 16) | + ((unsigned long)pccb->pdata[6] << 8) | + ((unsigned long)pccb->pdata[7]); + return 0; + } + + /* Read capacity (10) was insufficient. Use read capacity (16). */ + memset(pccb->cmd, '\0', sizeof(pccb->cmd)); + pccb->cmd[0] = SCSI_RD_CAPAC16; + pccb->cmd[1] = 0x10; + pccb->cmdlen = 16; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ + + pccb->datalen = 16; + if (scsi_exec(pccb) != true) + return 1; + + *capacity = ((uint64_t)pccb->pdata[0] << 56) | + ((uint64_t)pccb->pdata[1] << 48) | + ((uint64_t)pccb->pdata[2] << 40) | + ((uint64_t)pccb->pdata[3] << 32) | + ((uint64_t)pccb->pdata[4] << 24) | + ((uint64_t)pccb->pdata[5] << 16) | + ((uint64_t)pccb->pdata[6] << 8) | + ((uint64_t)pccb->pdata[7]); + + *blksz = ((uint64_t)pccb->pdata[8] << 56) | + ((uint64_t)pccb->pdata[9] << 48) | + ((uint64_t)pccb->pdata[10] << 40) | + ((uint64_t)pccb->pdata[11] << 32) | + ((uint64_t)pccb->pdata[12] << 24) | + ((uint64_t)pccb->pdata[13] << 16) | + ((uint64_t)pccb->pdata[14] << 8) | + ((uint64_t)pccb->pdata[15]); + + return 0; +} + + +/* + * Some setup (fill-in) routines + */ +void scsi_setup_test_unit_ready(ccb *pccb) +{ + pccb->cmd[0] = SCSI_TST_U_RDY; + pccb->cmd[1] = pccb->lun << 5; + pccb->cmd[2] = 0; + pccb->cmd[3] = 0; + pccb->cmd[4] = 0; + pccb->cmd[5] = 0; + pccb->cmdlen = 6; + pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ +} + +/* + * (re)-scan the scsi bus and reports scsi device info + * to the user if mode = 1 + */ +void scsi_scan(int mode) +{ + unsigned char i, perq, modi, lun; + lbaint_t capacity; + unsigned long blksz; + ccb *pccb = (ccb *)&tempccb; + + if (mode == 1) + printf("scanning bus for devices...\n"); + for (i = 0; i < CONFIG_SYS_SCSI_MAX_DEVICE; i++) { + scsi_dev_desc[i].target = 0xff; + scsi_dev_desc[i].lun = 0xff; + scsi_dev_desc[i].lba = 0; + scsi_dev_desc[i].blksz = 0; + scsi_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(scsi_dev_desc[i].log2blksz)); + scsi_dev_desc[i].type = DEV_TYPE_UNKNOWN; + scsi_dev_desc[i].vendor[0] = 0; + scsi_dev_desc[i].product[0] = 0; + scsi_dev_desc[i].revision[0] = 0; + scsi_dev_desc[i].removable = false; + scsi_dev_desc[i].if_type = IF_TYPE_SCSI; + scsi_dev_desc[i].devnum = i; + scsi_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + scsi_dev_desc[i].block_read = scsi_read; + scsi_dev_desc[i].block_write = scsi_write; + } + scsi_max_devs = 0; + for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { + pccb->target = i; + for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) { + pccb->lun = lun; + pccb->pdata = (unsigned char *)&tempbuff; + pccb->datalen = 512; + scsi_setup_inquiry(pccb); + if (scsi_exec(pccb) != true) { + if (pccb->contr_stat == SCSI_SEL_TIME_OUT) { + /* + * selection timeout => assuming no + * device present + */ + debug("Selection timeout ID %d\n", + pccb->target); + continue; + } + scsi_print_error(pccb); + continue; + } + perq = tempbuff[0]; + modi = tempbuff[1]; + if ((perq & 0x1f) == 0x1f) + continue; /* skip unknown devices */ + if ((modi & 0x80) == 0x80) /* drive is removable */ + scsi_dev_desc[scsi_max_devs].removable = true; + /* get info for this device */ + scsi_ident_cpy((unsigned char *)&scsi_dev_desc + [scsi_max_devs].vendor[0], + &tempbuff[8], 8); + scsi_ident_cpy((unsigned char *)&scsi_dev_desc + [scsi_max_devs].product[0], + &tempbuff[16], 16); + scsi_ident_cpy((unsigned char *)&scsi_dev_desc + [scsi_max_devs].revision[0], + &tempbuff[32], 4); + scsi_dev_desc[scsi_max_devs].target = pccb->target; + scsi_dev_desc[scsi_max_devs].lun = pccb->lun; + + pccb->datalen = 0; + scsi_setup_test_unit_ready(pccb); + if (scsi_exec(pccb) != true) { + if (scsi_dev_desc[scsi_max_devs].removable) { + scsi_dev_desc[scsi_max_devs].type = + perq; + goto removable; + } + scsi_print_error(pccb); + continue; + } + if (scsi_read_capacity(pccb, &capacity, &blksz)) { + scsi_print_error(pccb); + continue; + } + scsi_dev_desc[scsi_max_devs].lba = capacity; + scsi_dev_desc[scsi_max_devs].blksz = blksz; + scsi_dev_desc[scsi_max_devs].log2blksz = + LOG2(scsi_dev_desc[scsi_max_devs].blksz); + scsi_dev_desc[scsi_max_devs].type = perq; + part_init(&scsi_dev_desc[scsi_max_devs]); +removable: + if (mode == 1) { + printf(" Device %d: ", scsi_max_devs); + dev_print(&scsi_dev_desc[scsi_max_devs]); + } /* if mode */ + scsi_max_devs++; + } /* next LUN */ + } + if (scsi_max_devs > 0) + scsi_curr_dev = 0; + else + scsi_curr_dev = -1; + + printf("Found %d device(s).\n", scsi_max_devs); +#ifndef CONFIG_SPL_BUILD + setenv_ulong("scsidevs", scsi_max_devs); +#endif +} + +U_BOOT_LEGACY_BLK(scsi) = { + .if_typename = "sata", + .if_type = IF_TYPE_SCSI, + .max_devs = CONFIG_SYS_SCSI_MAX_DEVICE, + .desc = scsi_dev_desc, +};

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
At present the SCSI command code includes both the command-processing code and the core SCSI functions and data structures.
Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly. This functions use the new legacy block functions.
With this commit:
- There is no CONFIG option referenced from the command code
- The concept of a 'current SCSI device' is confined to the command code
This will make it easier to convert this code to driver model.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
cmd/Makefile | 6 - cmd/scsi.c | 626 +++----------------------------------------------------- common/Makefile | 4 + common/scsi.c | 567 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 600 insertions(+), 603 deletions(-) create mode 100644 common/scsi.c
Applied to u-boot-dm.

At present the IDE command code includes both the command-processing code and the core IDE functions and data structures.
Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly.
With this commit: - Most CONFIG option are referenced from the non-command code - The concept of a 'current IDE device' is confined to the command code
This will make it easier to convert this code to driver model.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
cmd/ide.c | 1297 +------------------------------------------------------ common/Makefile | 1 + common/ide.c | 1206 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1228 insertions(+), 1276 deletions(-) create mode 100644 common/ide.c
diff --git a/cmd/ide.c b/cmd/ide.c index db26f43..c942744 100644 --- a/cmd/ide.c +++ b/cmd/ide.c @@ -29,717 +29,9 @@ # include <status_led.h> #endif
-#ifdef __PPC__ -# define EIEIO __asm__ volatile ("eieio") -# define SYNC __asm__ volatile ("sync") -#else -# define EIEIO /* nothing */ -# define SYNC /* nothing */ -#endif - -/* ------------------------------------------------------------------------- */ - /* Current I/O Device */ static int curr_device = -1;
-/* Current offset for IDE0 / IDE1 bus access */ -ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = { -#if defined(CONFIG_SYS_ATA_IDE0_OFFSET) - CONFIG_SYS_ATA_IDE0_OFFSET, -#endif -#if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1) - CONFIG_SYS_ATA_IDE1_OFFSET, -#endif -}; - -static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS]; - -struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; -/* ------------------------------------------------------------------------- */ - -#define IDE_TIME_OUT 2000 /* 2 sec timeout */ - -#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */ - -#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */ - -#ifndef CONFIG_SYS_ATA_PORT_ADDR -#define CONFIG_SYS_ATA_PORT_ADDR(port) (port) -#endif - -#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ -# define DEVICE_LED(x) 0 -# define LED_IDE1 1 -# define LED_IDE2 2 -#endif - -#ifdef CONFIG_IDE_RESET -extern void ide_set_reset(int idereset); - -static void ide_reset(void) -{ - int i; - - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) - ide_bus_ok[i] = 0; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - - ide_set_reset(1); /* assert reset */ - - /* the reset signal shall be asserted for et least 25 us */ - udelay(25); - - WATCHDOG_RESET(); - - /* de-assert RESET signal */ - ide_set_reset(0); - - /* wait 250 ms */ - for (i = 0; i < 250; ++i) - udelay(1000); -} -#else -#define ide_reset() /* dummy */ -#endif /* CONFIG_IDE_RESET */ - -/* - * Wait until Busy bit is off, or timeout (in ms) - * Return last status - */ -static uchar ide_wait(int dev, ulong t) -{ - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { - udelay(100); - if (delay-- == 0) - break; - } - return c; -} - -/* - * copy src to dest, skipping leading and trailing blanks and null - * terminate the string - * "len" is the size of available memory including the terminating '\0' - */ -static void ident_cpy(unsigned char *dst, unsigned char *src, - unsigned int len) -{ - unsigned char *end, *last; - - last = dst; - end = src + len - 1; - - /* reserve space for '\0' */ - if (len < 2) - goto OUT; - - /* skip leading white space */ - while ((*src) && (src < end) && (*src == ' ')) - ++src; - - /* copy string, omitting trailing white space */ - while ((*src) && (src < end)) { - *dst++ = *src; - if (*src++ != ' ') - last = dst; - } -OUT: - *last = '\0'; -} - -#ifdef CONFIG_ATAPI -/**************************************************************************** - * ATAPI Support - */ - -#if defined(CONFIG_IDE_SWAP_IO) -/* since ATAPI may use commands with not 4 bytes alligned length - * we have our own transfer functions, 2 bytes alligned */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *)sect_buf; - - debug("in output data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { - EIEIO; - *pbuf = *dbuf++; - } -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *)sect_buf; - - debug("in input data shorts base for read is %lx\n", - (unsigned long) pbuf); - - while (shorts--) { - EIEIO; - *dbuf++ = *pbuf; - } -} - -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) -{ - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); -} - -#endif /* CONFIG_IDE_SWAP_IO */ - -/* - * Wait until (Status & mask) == res, or timeout (in ms) - * Return last status - * This is used since some ATAPI CD ROMs clears their Busy Bit first - * and then they set their DRQ Bit - */ -static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) -{ - ulong delay = 10 * t; /* poll every 100 us */ - uchar c; - - /* prevents to read the status before valid */ - c = ide_inb(dev, ATA_DEV_CTL); - - while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { - /* break if error occurs (doesn't make sense to wait more) */ - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) - break; - udelay(100); - if (delay-- == 0) - break; - } - return c; -} - -/* - * issue an atapi command - */ -unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char c, err, mask, res; - int n; - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - mask = ATA_STAT_BUSY | ATA_STAT_DRQ; - res = 0; - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - printf("ATAPI_ISSUE: device %d not ready status %X\n", device, - c); - err = 0xFF; - goto AI_OUT; - } - /* write taskfile */ - ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_SECT_NUM, 0); - ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); - ide_outb(device, ATA_CYL_HIGH, - (unsigned char) ((buflen >> 8) & 0xFF)); - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - - ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); - udelay(50); - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - - if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ - printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", - device, c); - err = 0xFF; - goto AI_OUT; - } - - /* write command block */ - ide_output_data_shorts(device, (unsigned short *)ccb, ccblen / 2); - - /* ATAPI Command written wait for completition */ - udelay(5000); /* device must set bsy */ - - mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; - /* - * if no data wait for DRQ = 0 BSY = 0 - * if data wait for DRQ = 1 BSY = 0 - */ - res = 0; - if (buflen) - res = ATA_STAT_DRQ; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & mask) != res) { - if (c & ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG)) >> 4; - debug("atapi_issue 1 returned sense key %X status %02X\n", - err, c); - } else { - printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", - ccb[0], c); - err = 0xFF; - } - goto AI_OUT; - } - n = ide_inb(device, ATA_CYL_HIGH); - n <<= 8; - n += ide_inb(device, ATA_CYL_LOW); - if (n > buflen) { - printf("ERROR, transfer bytes %d requested only %d\n", n, - buflen); - err = 0xff; - goto AI_OUT; - } - if ((n == 0) && (buflen < 0)) { - printf("ERROR, transfer bytes %d requested %d\n", n, buflen); - err = 0xff; - goto AI_OUT; - } - if (n != buflen) { - debug("WARNING, transfer bytes %d not equal with requested %d\n", - n, buflen); - } - if (n != 0) { /* data transfer */ - debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); - /* we transfer shorts */ - n >>= 1; - /* ok now decide if it is an in or output */ - if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) { - debug("Write to device\n"); - ide_output_data_shorts(device, (unsigned short *)buffer, - n); - } else { - debug("Read from device @ %p shorts %d\n", buffer, n); - ide_input_data_shorts(device, (unsigned short *)buffer, - n); - } - } - udelay(5000); /* seems that some CD ROMs need this... */ - mask = ATA_STAT_BUSY | ATA_STAT_ERR; - res = 0; - c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { - err = (ide_inb(device, ATA_ERROR_REG) >> 4); - debug("atapi_issue 2 returned sense key %X status %X\n", err, - c); - } else { - err = 0; - } -AI_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return err; -} - -/* - * sending the command to atapi_issue. If an status other than good - * returns, an request_sense will be issued - */ - -#define ATAPI_DRIVE_NOT_READY 100 -#define ATAPI_UNIT_ATTN 10 - -unsigned char atapi_issue_autoreq(int device, - unsigned char *ccb, - int ccblen, - unsigned char *buffer, int buflen) -{ - unsigned char sense_data[18], sense_ccb[12]; - unsigned char res, key, asc, ascq; - int notready, unitattn; - - unitattn = ATAPI_UNIT_ATTN; - notready = ATAPI_DRIVE_NOT_READY; - -retry: - res = atapi_issue(device, ccb, ccblen, buffer, buflen); - if (res == 0) - return 0; /* Ok */ - - if (res == 0xFF) - return 0xFF; /* error */ - - debug("(auto_req)atapi_issue returned sense key %X\n", res); - - memset(sense_ccb, 0, sizeof(sense_ccb)); - memset(sense_data, 0, sizeof(sense_data)); - sense_ccb[0] = ATAPI_CMD_REQ_SENSE; - sense_ccb[4] = 18; /* allocation Length */ - - res = atapi_issue(device, sense_ccb, 12, sense_data, 18); - key = (sense_data[2] & 0xF); - asc = (sense_data[12]); - ascq = (sense_data[13]); - - debug("ATAPI_CMD_REQ_SENSE returned %x\n", res); - debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", - sense_data[0], key, asc, ascq); - - if ((key == 0)) - return 0; /* ok device ready */ - - if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ - if (unitattn-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); - goto error; - } - if ((asc == 0x4) && (ascq == 0x1)) { - /* not ready, but will be ready soon */ - if (notready-- > 0) { - udelay(200 * 1000); - goto retry; - } - printf("Drive not ready, tried %d times\n", - ATAPI_DRIVE_NOT_READY); - goto error; - } - if (asc == 0x3a) { - debug("Media not present\n"); - goto error; - } - - printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, - ascq); -error: - debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); - return 0xFF; -} - -/* - * atapi_read: - * we transfer only one block per command, since the multiple DRQ per - * command is not yet implemented - */ -#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ -#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ -#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) - -ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char ccb[12]; /* Command descriptor block */ - ulong cnt; - - debug("atapi_read dev %d start " LBAF " blocks " LBAF - " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); - - do { - if (blkcnt > ATAPI_READ_MAX_BLOCK) - cnt = ATAPI_READ_MAX_BLOCK; - else - cnt = blkcnt; - - ccb[0] = ATAPI_CMD_READ_12; - ccb[1] = 0; /* reserved */ - ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ - ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ - ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; - ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ - ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ - ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; - ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; - ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ - ccb[10] = 0; /* reserved */ - ccb[11] = 0; /* reserved */ - - if (atapi_issue_autoreq(device, ccb, 12, - (unsigned char *)buffer, - cnt * ATAPI_READ_BLOCK_SIZE) - == 0xFF) { - return n; - } - n += cnt; - blkcnt -= cnt; - blknr += cnt; - buffer += (cnt * ATAPI_READ_BLOCK_SIZE); - } while (blkcnt > 0); - return n; -} - -static void atapi_inquiry(struct blk_desc *dev_desc) -{ - unsigned char ccb[12]; /* Command descriptor block */ - unsigned char iobuf[64]; /* temp buf */ - unsigned char c; - int device; - - device = dev_desc->devnum; - dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ - dev_desc->block_read = atapi_read; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - - ccb[0] = ATAPI_CMD_INQUIRY; - ccb[4] = 40; /* allocation Legnth */ - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 40); - - debug("ATAPI_CMD_INQUIRY returned %x\n", c); - if (c != 0) - return; - - /* copy device ident strings */ - ident_cpy((unsigned char *)dev_desc->vendor, &iobuf[8], 8); - ident_cpy((unsigned char *)dev_desc->product, &iobuf[16], 16); - ident_cpy((unsigned char *)dev_desc->revision, &iobuf[32], 5); - - dev_desc->lun = 0; - dev_desc->lba = 0; - dev_desc->blksz = 0; - dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); - dev_desc->type = iobuf[0] & 0x1f; - - if ((iobuf[1] & 0x80) == 0x80) - dev_desc->removable = 1; - else - dev_desc->removable = 0; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_START_STOP; - ccb[4] = 0x03; /* start */ - - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); - - debug("ATAPI_CMD_START_STOP returned %x\n", c); - if (c != 0) - return; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); - - debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); - if (c != 0) - return; - - memset(ccb, 0, sizeof(ccb)); - memset(iobuf, 0, sizeof(iobuf)); - ccb[0] = ATAPI_CMD_READ_CAP; - c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 8); - debug("ATAPI_CMD_READ_CAP returned %x\n", c); - if (c != 0) - return; - - debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", - iobuf[0], iobuf[1], iobuf[2], iobuf[3], - iobuf[4], iobuf[5], iobuf[6], iobuf[7]); - - dev_desc->lba = ((unsigned long) iobuf[0] << 24) + - ((unsigned long) iobuf[1] << 16) + - ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); - dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + - ((unsigned long) iobuf[5] << 16) + - ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); - dev_desc->log2blksz = LOG2(dev_desc->blksz); -#ifdef CONFIG_LBA48 - /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ - dev_desc->lba48 = 0; -#endif - return; -} - -#endif /* CONFIG_ATAPI */ - -static void ide_ident(struct blk_desc *dev_desc) -{ - unsigned char c; - hd_driveid_t iop; - -#ifdef CONFIG_ATAPI - int retries = 0; -#endif - int device; - - device = dev_desc->devnum; - printf(" Device %d: ", device); - - ide_led(DEVICE_LED(device), 1); /* LED on */ - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - dev_desc->if_type = IF_TYPE_IDE; -#ifdef CONFIG_ATAPI - - retries = 0; - - /* Warning: This will be tricky to read */ - while (retries <= 1) { - /* check signature */ - if ((ide_inb(device, ATA_SECT_CNT) == 0x01) && - (ide_inb(device, ATA_SECT_NUM) == 0x01) && - (ide_inb(device, ATA_CYL_LOW) == 0x14) && - (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) { - /* ATAPI Signature found */ - dev_desc->if_type = IF_TYPE_ATAPI; - /* - * Start Ident Command - */ - ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT); - /* - * Wait for completion - ATAPI devices need more time - * to become ready - */ - c = ide_wait(device, ATAPI_TIME_OUT); - } else -#endif - { - /* - * Start Ident Command - */ - ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT); - - /* - * Wait for completion - */ - c = ide_wait(device, IDE_TIME_OUT); - } - ide_led(DEVICE_LED(device), 0); /* LED off */ - - if (((c & ATA_STAT_DRQ) == 0) || - ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) { -#ifdef CONFIG_ATAPI - { - /* - * Need to soft reset the device - * in case it's an ATAPI... - */ - debug("Retrying...\n"); - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - udelay(100000); - ide_outb(device, ATA_COMMAND, 0x08); - udelay(500000); /* 500 ms */ - } - /* - * Select device - */ - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - retries++; -#else - return; -#endif - } -#ifdef CONFIG_ATAPI - else - break; - } /* see above - ugly to read */ - - if (retries == 2) /* Not found */ - return; -#endif - - ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS); - - ident_cpy((unsigned char *)dev_desc->revision, iop.fw_rev, - sizeof(dev_desc->revision)); - ident_cpy((unsigned char *)dev_desc->vendor, iop.model, - sizeof(dev_desc->vendor)); - ident_cpy((unsigned char *)dev_desc->product, iop.serial_no, - sizeof(dev_desc->product)); -#ifdef __LITTLE_ENDIAN - /* - * firmware revision, model, and serial number have Big Endian Byte - * order in Word. Convert all three to little endian. - * - * See CF+ and CompactFlash Specification Revision 2.0: - * 6.2.1.6: Identify Drive, Table 39 for more details - */ - - strswab(dev_desc->revision); - strswab(dev_desc->vendor); - strswab(dev_desc->product); -#endif /* __LITTLE_ENDIAN */ - - if ((iop.config & 0x0080) == 0x0080) - dev_desc->removable = 1; - else - dev_desc->removable = 0; - -#ifdef CONFIG_ATAPI - if (dev_desc->if_type == IF_TYPE_ATAPI) { - atapi_inquiry(dev_desc); - return; - } -#endif /* CONFIG_ATAPI */ - -#ifdef __BIG_ENDIAN - /* swap shorts */ - dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16); -#else /* ! __BIG_ENDIAN */ - /* - * do not swap shorts on little endian - * - * See CF+ and CompactFlash Specification Revision 2.0: - * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details. - */ - dev_desc->lba = iop.lba_capacity; -#endif /* __BIG_ENDIAN */ - -#ifdef CONFIG_LBA48 - if (iop.command_set_2 & 0x0400) { /* LBA 48 support */ - dev_desc->lba48 = 1; - dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] | - ((unsigned long long) iop.lba48_capacity[1] << 16) | - ((unsigned long long) iop.lba48_capacity[2] << 32) | - ((unsigned long long) iop.lba48_capacity[3] << 48); - } else { - dev_desc->lba48 = 0; - } -#endif /* CONFIG_LBA48 */ - /* assuming HD */ - dev_desc->type = DEV_TYPE_HARDDISK; - dev_desc->blksz = ATA_BLOCKSIZE; - dev_desc->log2blksz = LOG2(dev_desc->blksz); - dev_desc->lun = 0; /* just to fill something in... */ - -#if 0 /* only used to test the powersaving mode, - * if enabled, the drive goes after 5 sec - * in standby mode */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = ide_wait(device, IDE_TIME_OUT); - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, 0); - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, 0xe3); - udelay(50); - c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ -#endif -} - -/* ------------------------------------------------------------------------- */ - int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) { int rcode = 0; @@ -759,79 +51,41 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) ide_init(); return 0; } else if (strncmp(argv[1], "inf", 3) == 0) { - int i; - - putc('\n'); - - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { - if (ide_dev_desc[i].type == DEV_TYPE_UNKNOWN) - continue; /* list only known devices */ - printf("IDE device %d: ", i); - dev_print(&ide_dev_desc[i]); - } + blk_list_devices(IF_TYPE_IDE); return 0;
} else if (strncmp(argv[1], "dev", 3) == 0) { - if (curr_device < 0 || - curr_device >= CONFIG_SYS_IDE_MAXDEVICE) { - puts("\nno IDE devices available\n"); - return 1; + if (blk_print_device_num(IF_TYPE_IDE, curr_device)) { + printf("\nno IDE devices available\n"); + return CMD_RET_FAILURE; } - printf("\nIDE device %d: ", curr_device); - dev_print(&ide_dev_desc[curr_device]); + return 0; } else if (strncmp(argv[1], "part", 4) == 0) { - int dev, ok; - - for (ok = 0, dev = 0; - dev < CONFIG_SYS_IDE_MAXDEVICE; - ++dev) { - if (ide_dev_desc[dev].part_type != - PART_TYPE_UNKNOWN) { - ++ok; - if (dev) - putc('\n'); - part_print(&ide_dev_desc[dev]); - } - } - if (!ok) { - puts("\nno IDE devices available\n"); - rcode++; - } - return rcode; + if (blk_list_part(IF_TYPE_IDE)) + printf("\nno IDE devices available\n"); + return 1; } return CMD_RET_USAGE; case 3: if (strncmp(argv[1], "dev", 3) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10);
- printf("\nIDE device %d: ", dev); - if (dev >= CONFIG_SYS_IDE_MAXDEVICE) { - puts("unknown device\n"); - return 1; + if (!blk_show_device(IF_TYPE_IDE, dev)) { + curr_device = dev; + printf("... is now current device\n"); + } else { + return CMD_RET_FAILURE; } - dev_print(&ide_dev_desc[dev]); - /*ide_print (dev); */ - - if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; - - curr_device = dev; - - puts("... is now current device\n"); - return 0; } else if (strncmp(argv[1], "part", 4) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10);
- if (ide_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - part_print(&ide_dev_desc[dev]); - } else { - printf("\nIDE device %d not available\n", - dev); - rcode = 1; + if (blk_print_part_devnum(IF_TYPE_IDE, dev)) { + printf("\nIDE device %d not available\n", dev); + return CMD_RET_FAILURE; } - return rcode; + return 1; }
return CMD_RET_USAGE; @@ -841,7 +95,6 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) if (strcmp(argv[1], "read") == 0) { ulong addr = simple_strtoul(argv[2], NULL, 16); ulong cnt = simple_strtoul(argv[4], NULL, 16); - struct blk_desc *dev_desc; ulong n;
#ifdef CONFIG_SYS_64BIT_LBA @@ -856,11 +109,8 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) curr_device, blk, cnt); #endif
- dev_desc = &ide_dev_desc[curr_device]; - n = blk_dread(dev_desc, blk, cnt, (ulong *)addr); - /* flush cache after read */ - flush_cache(addr, - cnt * ide_dev_desc[curr_device].blksz); + n = blk_read_devnum(IF_TYPE_IDE, curr_device, blk, cnt, + (ulong *)addr);
printf("%ld blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); @@ -884,8 +134,8 @@ int do_ide(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) printf("\nIDE write: device %d block # %ld, count %ld...", curr_device, blk, cnt); #endif - n = ide_write(&ide_dev_desc[curr_device], blk, cnt, - (ulong *)addr); + n = blk_write_devnum(IF_TYPE_IDE, curr_device, blk, cnt, + (ulong *)addr);
printf("%ld blocks written: %s\n", n, n == cnt ? "OK" : "ERROR"); @@ -906,511 +156,6 @@ int do_diskboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) return common_diskboot(cmdtp, "ide", argc, argv); }
-/* ------------------------------------------------------------------------- */ - -__weak void ide_led(uchar led, uchar status) -{ -#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */ - static uchar led_buffer; /* Buffer for current LED status */ - - uchar *led_port = LED_PORT; - - if (status) /* switch LED on */ - led_buffer |= led; - else /* switch LED off */ - led_buffer &= ~led; - - *led_port = led_buffer; -#endif -} - -/* ------------------------------------------------------------------------- */ - -__weak void ide_outb(int dev, int port, unsigned char val) -{ - debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n", - dev, port, val, - (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); - -#if defined(CONFIG_IDE_AHB) - if (port) { - /* write command */ - ide_write_register(dev, port, val); - } else { - /* write data */ - outb(val, (ATA_CURR_BASE(dev))); - } -#else - outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif -} - -__weak unsigned char ide_inb(int dev, int port) -{ - uchar val; - -#if defined(CONFIG_IDE_AHB) - val = ide_read_register(dev, port); -#else - val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); -#endif - - debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", - dev, port, - (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val); - return val; -} - -void ide_init(void) -{ - unsigned char c; - int i, bus; - -#ifdef CONFIG_IDE_8xx_PCCARD - extern int ide_devices_found; /* Initialized in check_ide_device() */ -#endif /* CONFIG_IDE_8xx_PCCARD */ - -#ifdef CONFIG_IDE_PREINIT - WATCHDOG_RESET(); - - if (ide_preinit()) { - puts("ide_preinit failed\n"); - return; - } -#endif /* CONFIG_IDE_PREINIT */ - - WATCHDOG_RESET(); - - /* - * Reset the IDE just to be sure. - * Light LED's to show - */ - ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */ - - /* ATAPI Drives seems to need a proper IDE Reset */ - ide_reset(); - -#ifdef CONFIG_IDE_INIT_POSTRESET - WATCHDOG_RESET(); - - if (ide_init_postreset()) { - puts("ide_preinit_postreset failed\n"); - return; - } -#endif /* CONFIG_IDE_INIT_POSTRESET */ - - /* - * Wait for IDE to get ready. - * According to spec, this can take up to 31 seconds! - */ - for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) { - int dev = - bus * (CONFIG_SYS_IDE_MAXDEVICE / - CONFIG_SYS_IDE_MAXBUS); - -#ifdef CONFIG_IDE_8xx_PCCARD - /* Skip non-ide devices from probing */ - if ((ide_devices_found & (1 << bus)) == 0) { - ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ - continue; - } -#endif - printf("Bus %d: ", bus); - - ide_bus_ok[bus] = 0; - - /* Select device - */ - udelay(100000); /* 100 ms */ - ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); - udelay(100000); /* 100 ms */ - i = 0; - do { - udelay(10000); /* 10 ms */ - - c = ide_inb(dev, ATA_STATUS); - i++; - if (i > (ATA_RESET_TIME * 100)) { - puts("** Timeout **\n"); - /* LED's off */ - ide_led((LED_IDE1 | LED_IDE2), 0); - return; - } - if ((i >= 100) && ((i % 100) == 0)) - putc('.'); - - } while (c & ATA_STAT_BUSY); - - if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { - puts("not available "); - debug("Status = 0x%02X ", c); -#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ - } else if ((c & ATA_STAT_READY) == 0) { - puts("not available "); - debug("Status = 0x%02X ", c); -#endif - } else { - puts("OK "); - ide_bus_ok[bus] = 1; - } - WATCHDOG_RESET(); - } - - putc('\n'); - - ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ - - curr_device = -1; - for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { - int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; - ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; - ide_dev_desc[i].if_type = IF_TYPE_IDE; - ide_dev_desc[i].devnum = i; - ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - ide_dev_desc[i].blksz = 0; - ide_dev_desc[i].log2blksz = - LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); - ide_dev_desc[i].lba = 0; - ide_dev_desc[i].block_read = ide_read; - ide_dev_desc[i].block_write = ide_write; - if (!ide_bus_ok[IDE_BUS(i)]) - continue; - ide_led(led, 1); /* LED on */ - ide_ident(&ide_dev_desc[i]); - ide_led(led, 0); /* LED off */ - dev_print(&ide_dev_desc[i]); - - if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { - /* initialize partition type */ - part_init(&ide_dev_desc[i]); - if (curr_device < 0) - curr_device = i; - } - } - WATCHDOG_RESET(); -} - -/* ------------------------------------------------------------------------- */ - -#ifdef CONFIG_PARTITIONS -struct blk_desc *ide_get_dev(int dev) -{ - return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; -} -#endif - -/* ------------------------------------------------------------------------- */ - -/* We only need to swap data if we are running on a big endian cpu. */ -#if defined(__LITTLE_ENDIAN) -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) -{ - ide_input_data(dev, sect_buf, words); -} -#else -__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) -{ - volatile ushort *pbuf = - (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - ushort *dbuf = (ushort *)sect_buf; - - debug("in input swap data base for read is %lx\n", - (unsigned long) pbuf); - - while (words--) { -#ifdef __MIPS__ - *dbuf++ = swab16p((u16 *)pbuf); - *dbuf++ = swab16p((u16 *)pbuf); -#else - *dbuf++ = ld_le16(pbuf); - *dbuf++ = ld_le16(pbuf); -#endif /* !MIPS */ - } -} -#endif /* __LITTLE_ENDIAN */ - - -#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_output_data(int dev, const ulong *sect_buf, int words) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *)sect_buf; - while (words--) { - EIEIO; - *pbuf = *dbuf++; - EIEIO; - *pbuf = *dbuf++; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_output_data(int dev, const ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_write_data(dev, sect_buf, words); -#else - outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); -#endif -} -#endif /* CONFIG_IDE_SWAP_IO */ - -#if defined(CONFIG_IDE_SWAP_IO) -__weak void ide_input_data(int dev, ulong *sect_buf, int words) -{ - ushort *dbuf; - volatile ushort *pbuf; - - pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); - dbuf = (ushort *)sect_buf; - - debug("in input data base for read is %lx\n", (unsigned long) pbuf); - - while (words--) { - EIEIO; - *dbuf++ = *pbuf; - EIEIO; - *dbuf++ = *pbuf; - } -} -#else /* ! CONFIG_IDE_SWAP_IO */ -__weak void ide_input_data(int dev, ulong *sect_buf, int words) -{ -#if defined(CONFIG_IDE_AHB) - ide_read_data(dev, sect_buf, words); -#else - insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); -#endif -} - -#endif /* CONFIG_IDE_SWAP_IO */ - -/* ------------------------------------------------------------------------- */ - -ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char c; - unsigned char pwrsave = 0; /* power save */ - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n", - device, blknr, blkcnt, (ulong) buffer); - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } - - /* first check if the drive is in Powersaving mode, if yes, - * increase the timeout value */ - ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR); - udelay(50); - - c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto IDE_READ_E; - } - if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { - printf("No Powersaving mode %X\n", c); - } else { - c = ide_inb(device, ATA_SECT_CNT); - debug("Powersaving %02X\n", c); - if (c == 0) - pwrsave = 1; - } - - - while (blkcnt-- > 0) { - - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - break; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); -#ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); -#else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); -#endif - } -#endif - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); - ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); - -#ifdef CONFIG_LBA48 - if (lba48) { - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT); - - } else -#endif - { - ide_outb(device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); - ide_outb(device, ATA_COMMAND, ATA_CMD_READ); - } - - udelay(50); - - if (pwrsave) { - /* may take up to 4 sec */ - c = ide_wait(device, IDE_SPIN_UP_TIME_OUT); - pwrsave = 0; - } else { - /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); - } - - if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF - ": status %#02x\n", device, blknr, c); - break; - } - - ide_input_data(device, buffer, ATA_SECTORWORDS); - (void) ide_inb(device, ATA_STATUS); /* clear IRQ */ - - ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; - } -IDE_READ_E: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return n; -} - -/* ------------------------------------------------------------------------- */ - - -ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, - const void *buffer) -{ - int device = block_dev->devnum; - ulong n = 0; - unsigned char c; - -#ifdef CONFIG_LBA48 - unsigned char lba48 = 0; - - if (blknr & 0x0000fffff0000000ULL) { - /* more than 28 bits used, use 48bit mode */ - lba48 = 1; - } -#endif - - ide_led(DEVICE_LED(device), 1); /* LED on */ - - /* Select device - */ - ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); - - while (blkcnt-- > 0) { - c = ide_wait(device, IDE_TIME_OUT); - - if (c & ATA_STAT_BUSY) { - printf("IDE read: device %d not ready\n", device); - goto WR_OUT; - } -#ifdef CONFIG_LBA48 - if (lba48) { - /* write high bits */ - ide_outb(device, ATA_SECT_CNT, 0); - ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); -#ifdef CONFIG_SYS_64BIT_LBA - ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); -#else - ide_outb(device, ATA_LBA_MID, 0); - ide_outb(device, ATA_LBA_HIGH, 0); -#endif - } -#endif - ide_outb(device, ATA_SECT_CNT, 1); - ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); - ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); - ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); - -#ifdef CONFIG_LBA48 - if (lba48) { - ide_outb(device, ATA_DEV_HD, - ATA_LBA | ATA_DEVICE(device)); - ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT); - - } else -#endif - { - ide_outb(device, ATA_DEV_HD, ATA_LBA | - ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); - ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE); - } - - udelay(50); - - /* can't take over 500 ms */ - c = ide_wait(device, IDE_TIME_OUT); - - if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != - ATA_STAT_DRQ) { - printf("Error (no IRQ) dev %d blk " LBAF - ": status %#02x\n", device, blknr, c); - goto WR_OUT; - } - - ide_output_data(device, buffer, ATA_SECTORWORDS); - c = ide_inb(device, ATA_STATUS); /* clear IRQ */ - ++n; - ++blknr; - buffer += ATA_BLOCKSIZE; - } -WR_OUT: - ide_led(DEVICE_LED(device), 0); /* LED off */ - return n; -} - -/* ------------------------------------------------------------------------- */ - -#if defined(CONFIG_OF_IDE_FIXUP) -int ide_device_present(int dev) -{ - if (dev >= CONFIG_SYS_IDE_MAXBUS) - return 0; - return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1; -} -#endif -/* ------------------------------------------------------------------------- */ - U_BOOT_CMD(ide, 5, 1, do_ide, "IDE sub-system", "reset - reset IDE controller\n" diff --git a/common/Makefile b/common/Makefile index 397df61..1df5add 100644 --- a/common/Makefile +++ b/common/Makefile @@ -134,6 +134,7 @@ obj-y += dlmalloc.o ifdef CONFIG_SYS_MALLOC_F_LEN obj-y += malloc_simple.o endif +obj-$(CONFIG_CMD_IDE) += ide.o obj-y += image.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o obj-$(CONFIG_$(SPL_)OF_LIBFDT) += image-fdt.o diff --git a/common/ide.c b/common/ide.c new file mode 100644 index 0000000..adc1966 --- /dev/null +++ b/common/ide.c @@ -0,0 +1,1206 @@ +/* + * (C) Copyright 2000-2011 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <ata.h> +#include <ide.h> +#include <watchdog.h> +#include <asm/io.h> + +#ifdef __PPC__ +# define EIEIO __asm__ volatile ("eieio") +# define SYNC __asm__ volatile ("sync") +#else +# define EIEIO /* nothing */ +# define SYNC /* nothing */ +#endif + +/* Current offset for IDE0 / IDE1 bus access */ +ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS] = { +#if defined(CONFIG_SYS_ATA_IDE0_OFFSET) + CONFIG_SYS_ATA_IDE0_OFFSET, +#endif +#if defined(CONFIG_SYS_ATA_IDE1_OFFSET) && (CONFIG_SYS_IDE_MAXBUS > 1) + CONFIG_SYS_ATA_IDE1_OFFSET, +#endif +}; + +static int ide_bus_ok[CONFIG_SYS_IDE_MAXBUS]; + +struct blk_desc ide_dev_desc[CONFIG_SYS_IDE_MAXDEVICE]; + +#define IDE_TIME_OUT 2000 /* 2 sec timeout */ + +#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */ + +#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */ + +#ifndef CONFIG_SYS_ATA_PORT_ADDR +#define CONFIG_SYS_ATA_PORT_ADDR(port) (port) +#endif + +#ifndef CONFIG_IDE_LED /* define LED macros, they are not used anyways */ +# define DEVICE_LED(x) 0 +# define LED_IDE1 1 +# define LED_IDE2 2 +#endif + +#ifdef CONFIG_IDE_RESET +extern void ide_set_reset(int idereset); + +static void ide_reset(void) +{ + int i; + + for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; ++i) + ide_bus_ok[i] = 0; + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; + + ide_set_reset(1); /* assert reset */ + + /* the reset signal shall be asserted for et least 25 us */ + udelay(25); + + WATCHDOG_RESET(); + + /* de-assert RESET signal */ + ide_set_reset(0); + + /* wait 250 ms */ + for (i = 0; i < 250; ++i) + udelay(1000); +} +#else +#define ide_reset() /* dummy */ +#endif /* CONFIG_IDE_RESET */ + +/* + * Wait until Busy bit is off, or timeout (in ms) + * Return last status + */ +static uchar ide_wait(int dev, ulong t) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; + + while ((c = ide_inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { + udelay(100); + if (delay-- == 0) + break; + } + return c; +} + +/* + * copy src to dest, skipping leading and trailing blanks and null + * terminate the string + * "len" is the size of available memory including the terminating '\0' + */ +static void ident_cpy(unsigned char *dst, unsigned char *src, + unsigned int len) +{ + unsigned char *end, *last; + + last = dst; + end = src + len - 1; + + /* reserve space for '\0' */ + if (len < 2) + goto OUT; + + /* skip leading white space */ + while ((*src) && (src < end) && (*src == ' ')) + ++src; + + /* copy string, omitting trailing white space */ + while ((*src) && (src < end)) { + *dst++ = *src; + if (*src++ != ' ') + last = dst; + } +OUT: + *last = '\0'; +} + +#ifdef CONFIG_ATAPI +/**************************************************************************** + * ATAPI Support + */ + +#if defined(CONFIG_IDE_SWAP_IO) +/* since ATAPI may use commands with not 4 bytes alligned length + * we have our own transfer functions, 2 bytes alligned */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + + debug("in output data shorts base for read is %lx\n", + (unsigned long) pbuf); + + while (shorts--) { + EIEIO; + *pbuf = *dbuf++; + } +} + +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + + debug("in input data shorts base for read is %lx\n", + (unsigned long) pbuf); + + while (shorts--) { + EIEIO; + *dbuf++ = *pbuf; + } +} + +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +} + +__weak void ide_input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, shorts); +} + +#endif /* CONFIG_IDE_SWAP_IO */ + +/* + * Wait until (Status & mask) == res, or timeout (in ms) + * Return last status + * This is used since some ATAPI CD ROMs clears their Busy Bit first + * and then they set their DRQ Bit + */ +static uchar atapi_wait_mask(int dev, ulong t, uchar mask, uchar res) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; + + /* prevents to read the status before valid */ + c = ide_inb(dev, ATA_DEV_CTL); + + while (((c = ide_inb(dev, ATA_STATUS)) & mask) != res) { + /* break if error occurs (doesn't make sense to wait more) */ + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) + break; + udelay(100); + if (delay-- == 0) + break; + } + return c; +} + +/* + * issue an atapi command + */ +unsigned char atapi_issue(int device, unsigned char *ccb, int ccblen, + unsigned char *buffer, int buflen) +{ + unsigned char c, err, mask, res; + int n; + + ide_led(DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + mask = ATA_STAT_BUSY | ATA_STAT_DRQ; + res = 0; + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + printf("ATAPI_ISSUE: device %d not ready status %X\n", device, + c); + err = 0xFF; + goto AI_OUT; + } + /* write taskfile */ + ide_outb(device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_SECT_NUM, 0); + ide_outb(device, ATA_CYL_LOW, (unsigned char) (buflen & 0xFF)); + ide_outb(device, ATA_CYL_HIGH, + (unsigned char) ((buflen >> 8) & 0xFF)); + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + + ide_outb(device, ATA_COMMAND, ATAPI_CMD_PACKET); + udelay(50); + + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + + if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ + printf("ATAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n", + device, c); + err = 0xFF; + goto AI_OUT; + } + + /* write command block */ + ide_output_data_shorts(device, (unsigned short *)ccb, ccblen / 2); + + /* ATAPI Command written wait for completition */ + udelay(5000); /* device must set bsy */ + + mask = ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR; + /* + * if no data wait for DRQ = 0 BSY = 0 + * if data wait for DRQ = 1 BSY = 0 + */ + res = 0; + if (buflen) + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & mask) != res) { + if (c & ATA_STAT_ERR) { + err = (ide_inb(device, ATA_ERROR_REG)) >> 4; + debug("atapi_issue 1 returned sense key %X status %02X\n", + err, c); + } else { + printf("ATAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", + ccb[0], c); + err = 0xFF; + } + goto AI_OUT; + } + n = ide_inb(device, ATA_CYL_HIGH); + n <<= 8; + n += ide_inb(device, ATA_CYL_LOW); + if (n > buflen) { + printf("ERROR, transfer bytes %d requested only %d\n", n, + buflen); + err = 0xff; + goto AI_OUT; + } + if ((n == 0) && (buflen < 0)) { + printf("ERROR, transfer bytes %d requested %d\n", n, buflen); + err = 0xff; + goto AI_OUT; + } + if (n != buflen) { + debug("WARNING, transfer bytes %d not equal with requested %d\n", + n, buflen); + } + if (n != 0) { /* data transfer */ + debug("ATAPI_ISSUE: %d Bytes to transfer\n", n); + /* we transfer shorts */ + n >>= 1; + /* ok now decide if it is an in or output */ + if ((ide_inb(device, ATA_SECT_CNT) & 0x02) == 0) { + debug("Write to device\n"); + ide_output_data_shorts(device, (unsigned short *)buffer, + n); + } else { + debug("Read from device @ %p shorts %d\n", buffer, n); + ide_input_data_shorts(device, (unsigned short *)buffer, + n); + } + } + udelay(5000); /* seems that some CD ROMs need this... */ + mask = ATA_STAT_BUSY | ATA_STAT_ERR; + res = 0; + c = atapi_wait_mask(device, ATAPI_TIME_OUT, mask, res); + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + err = (ide_inb(device, ATA_ERROR_REG) >> 4); + debug("atapi_issue 2 returned sense key %X status %X\n", err, + c); + } else { + err = 0; + } +AI_OUT: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return err; +} + +/* + * sending the command to atapi_issue. If an status other than good + * returns, an request_sense will be issued + */ + +#define ATAPI_DRIVE_NOT_READY 100 +#define ATAPI_UNIT_ATTN 10 + +unsigned char atapi_issue_autoreq(int device, + unsigned char *ccb, + int ccblen, + unsigned char *buffer, int buflen) +{ + unsigned char sense_data[18], sense_ccb[12]; + unsigned char res, key, asc, ascq; + int notready, unitattn; + + unitattn = ATAPI_UNIT_ATTN; + notready = ATAPI_DRIVE_NOT_READY; + +retry: + res = atapi_issue(device, ccb, ccblen, buffer, buflen); + if (res == 0) + return 0; /* Ok */ + + if (res == 0xFF) + return 0xFF; /* error */ + + debug("(auto_req)atapi_issue returned sense key %X\n", res); + + memset(sense_ccb, 0, sizeof(sense_ccb)); + memset(sense_data, 0, sizeof(sense_data)); + sense_ccb[0] = ATAPI_CMD_REQ_SENSE; + sense_ccb[4] = 18; /* allocation Length */ + + res = atapi_issue(device, sense_ccb, 12, sense_data, 18); + key = (sense_data[2] & 0xF); + asc = (sense_data[12]); + ascq = (sense_data[13]); + + debug("ATAPI_CMD_REQ_SENSE returned %x\n", res); + debug(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", + sense_data[0], key, asc, ascq); + + if ((key == 0)) + return 0; /* ok device ready */ + + if ((key == 6) || (asc == 0x29) || (asc == 0x28)) { /* Unit Attention */ + if (unitattn-- > 0) { + udelay(200 * 1000); + goto retry; + } + printf("Unit Attention, tried %d\n", ATAPI_UNIT_ATTN); + goto error; + } + if ((asc == 0x4) && (ascq == 0x1)) { + /* not ready, but will be ready soon */ + if (notready-- > 0) { + udelay(200 * 1000); + goto retry; + } + printf("Drive not ready, tried %d times\n", + ATAPI_DRIVE_NOT_READY); + goto error; + } + if (asc == 0x3a) { + debug("Media not present\n"); + goto error; + } + + printf("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n", key, asc, + ascq); +error: + debug("ERROR Sense key %02X ASC %02X ASCQ %02X\n", key, asc, ascq); + return 0xFF; +} + +/* + * atapi_read: + * we transfer only one block per command, since the multiple DRQ per + * command is not yet implemented + */ +#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ +#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ +#define ATAPI_READ_MAX_BLOCK (ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE) + +ulong atapi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +{ + int device = block_dev->devnum; + ulong n = 0; + unsigned char ccb[12]; /* Command descriptor block */ + ulong cnt; + + debug("atapi_read dev %d start " LBAF " blocks " LBAF + " buffer at %lX\n", device, blknr, blkcnt, (ulong) buffer); + + do { + if (blkcnt > ATAPI_READ_MAX_BLOCK) + cnt = ATAPI_READ_MAX_BLOCK; + else + cnt = blkcnt; + + ccb[0] = ATAPI_CMD_READ_12; + ccb[1] = 0; /* reserved */ + ccb[2] = (unsigned char) (blknr >> 24) & 0xFF; /* MSB Block */ + ccb[3] = (unsigned char) (blknr >> 16) & 0xFF; /* */ + ccb[4] = (unsigned char) (blknr >> 8) & 0xFF; + ccb[5] = (unsigned char) blknr & 0xFF; /* LSB Block */ + ccb[6] = (unsigned char) (cnt >> 24) & 0xFF; /* MSB Block cnt */ + ccb[7] = (unsigned char) (cnt >> 16) & 0xFF; + ccb[8] = (unsigned char) (cnt >> 8) & 0xFF; + ccb[9] = (unsigned char) cnt & 0xFF; /* LSB Block */ + ccb[10] = 0; /* reserved */ + ccb[11] = 0; /* reserved */ + + if (atapi_issue_autoreq(device, ccb, 12, + (unsigned char *)buffer, + cnt * ATAPI_READ_BLOCK_SIZE) + == 0xFF) { + return n; + } + n += cnt; + blkcnt -= cnt; + blknr += cnt; + buffer += (cnt * ATAPI_READ_BLOCK_SIZE); + } while (blkcnt > 0); + return n; +} + +static void atapi_inquiry(struct blk_desc *dev_desc) +{ + unsigned char ccb[12]; /* Command descriptor block */ + unsigned char iobuf[64]; /* temp buf */ + unsigned char c; + int device; + + device = dev_desc->devnum; + dev_desc->type = DEV_TYPE_UNKNOWN; /* not yet valid */ + dev_desc->block_read = atapi_read; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + + ccb[0] = ATAPI_CMD_INQUIRY; + ccb[4] = 40; /* allocation Legnth */ + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 40); + + debug("ATAPI_CMD_INQUIRY returned %x\n", c); + if (c != 0) + return; + + /* copy device ident strings */ + ident_cpy((unsigned char *)dev_desc->vendor, &iobuf[8], 8); + ident_cpy((unsigned char *)dev_desc->product, &iobuf[16], 16); + ident_cpy((unsigned char *)dev_desc->revision, &iobuf[32], 5); + + dev_desc->lun = 0; + dev_desc->lba = 0; + dev_desc->blksz = 0; + dev_desc->log2blksz = LOG2_INVALID(typeof(dev_desc->log2blksz)); + dev_desc->type = iobuf[0] & 0x1f; + + if ((iobuf[1] & 0x80) == 0x80) + dev_desc->removable = 1; + else + dev_desc->removable = 0; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_START_STOP; + ccb[4] = 0x03; /* start */ + + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); + + debug("ATAPI_CMD_START_STOP returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 0); + + debug("ATAPI_CMD_UNIT_TEST_READY returned %x\n", c); + if (c != 0) + return; + + memset(ccb, 0, sizeof(ccb)); + memset(iobuf, 0, sizeof(iobuf)); + ccb[0] = ATAPI_CMD_READ_CAP; + c = atapi_issue_autoreq(device, ccb, 12, (unsigned char *)iobuf, 8); + debug("ATAPI_CMD_READ_CAP returned %x\n", c); + if (c != 0) + return; + + debug("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", + iobuf[0], iobuf[1], iobuf[2], iobuf[3], + iobuf[4], iobuf[5], iobuf[6], iobuf[7]); + + dev_desc->lba = ((unsigned long) iobuf[0] << 24) + + ((unsigned long) iobuf[1] << 16) + + ((unsigned long) iobuf[2] << 8) + ((unsigned long) iobuf[3]); + dev_desc->blksz = ((unsigned long) iobuf[4] << 24) + + ((unsigned long) iobuf[5] << 16) + + ((unsigned long) iobuf[6] << 8) + ((unsigned long) iobuf[7]); + dev_desc->log2blksz = LOG2(dev_desc->blksz); +#ifdef CONFIG_LBA48 + /* ATAPI devices cannot use 48bit addressing (ATA/ATAPI v7) */ + dev_desc->lba48 = 0; +#endif + return; +} + +#endif /* CONFIG_ATAPI */ + +static void ide_ident(struct blk_desc *dev_desc) +{ + unsigned char c; + hd_driveid_t iop; + +#ifdef CONFIG_ATAPI + int retries = 0; +#endif + int device; + + device = dev_desc->devnum; + printf(" Device %d: ", device); + + ide_led(DEVICE_LED(device), 1); /* LED on */ + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + dev_desc->if_type = IF_TYPE_IDE; +#ifdef CONFIG_ATAPI + + retries = 0; + + /* Warning: This will be tricky to read */ + while (retries <= 1) { + /* check signature */ + if ((ide_inb(device, ATA_SECT_CNT) == 0x01) && + (ide_inb(device, ATA_SECT_NUM) == 0x01) && + (ide_inb(device, ATA_CYL_LOW) == 0x14) && + (ide_inb(device, ATA_CYL_HIGH) == 0xEB)) { + /* ATAPI Signature found */ + dev_desc->if_type = IF_TYPE_ATAPI; + /* + * Start Ident Command + */ + ide_outb(device, ATA_COMMAND, ATAPI_CMD_IDENT); + /* + * Wait for completion - ATAPI devices need more time + * to become ready + */ + c = ide_wait(device, ATAPI_TIME_OUT); + } else +#endif + { + /* + * Start Ident Command + */ + ide_outb(device, ATA_COMMAND, ATA_CMD_IDENT); + + /* + * Wait for completion + */ + c = ide_wait(device, IDE_TIME_OUT); + } + ide_led(DEVICE_LED(device), 0); /* LED off */ + + if (((c & ATA_STAT_DRQ) == 0) || + ((c & (ATA_STAT_FAULT | ATA_STAT_ERR)) != 0)) { +#ifdef CONFIG_ATAPI + { + /* + * Need to soft reset the device + * in case it's an ATAPI... + */ + debug("Retrying...\n"); + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + udelay(100000); + ide_outb(device, ATA_COMMAND, 0x08); + udelay(500000); /* 500 ms */ + } + /* + * Select device + */ + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + retries++; +#else + return; +#endif + } +#ifdef CONFIG_ATAPI + else + break; + } /* see above - ugly to read */ + + if (retries == 2) /* Not found */ + return; +#endif + + ide_input_swap_data(device, (ulong *)&iop, ATA_SECTORWORDS); + + ident_cpy((unsigned char *)dev_desc->revision, iop.fw_rev, + sizeof(dev_desc->revision)); + ident_cpy((unsigned char *)dev_desc->vendor, iop.model, + sizeof(dev_desc->vendor)); + ident_cpy((unsigned char *)dev_desc->product, iop.serial_no, + sizeof(dev_desc->product)); +#ifdef __LITTLE_ENDIAN + /* + * firmware revision, model, and serial number have Big Endian Byte + * order in Word. Convert all three to little endian. + * + * See CF+ and CompactFlash Specification Revision 2.0: + * 6.2.1.6: Identify Drive, Table 39 for more details + */ + + strswab(dev_desc->revision); + strswab(dev_desc->vendor); + strswab(dev_desc->product); +#endif /* __LITTLE_ENDIAN */ + + if ((iop.config & 0x0080) == 0x0080) + dev_desc->removable = 1; + else + dev_desc->removable = 0; + +#ifdef CONFIG_ATAPI + if (dev_desc->if_type == IF_TYPE_ATAPI) { + atapi_inquiry(dev_desc); + return; + } +#endif /* CONFIG_ATAPI */ + +#ifdef __BIG_ENDIAN + /* swap shorts */ + dev_desc->lba = (iop.lba_capacity << 16) | (iop.lba_capacity >> 16); +#else /* ! __BIG_ENDIAN */ + /* + * do not swap shorts on little endian + * + * See CF+ and CompactFlash Specification Revision 2.0: + * 6.2.1.6: Identfy Drive, Table 39, Word Address 57-58 for details. + */ + dev_desc->lba = iop.lba_capacity; +#endif /* __BIG_ENDIAN */ + +#ifdef CONFIG_LBA48 + if (iop.command_set_2 & 0x0400) { /* LBA 48 support */ + dev_desc->lba48 = 1; + dev_desc->lba = (unsigned long long) iop.lba48_capacity[0] | + ((unsigned long long) iop.lba48_capacity[1] << 16) | + ((unsigned long long) iop.lba48_capacity[2] << 32) | + ((unsigned long long) iop.lba48_capacity[3] << 48); + } else { + dev_desc->lba48 = 0; + } +#endif /* CONFIG_LBA48 */ + /* assuming HD */ + dev_desc->type = DEV_TYPE_HARDDISK; + dev_desc->blksz = ATA_BLOCKSIZE; + dev_desc->log2blksz = LOG2(dev_desc->blksz); + dev_desc->lun = 0; /* just to fill something in... */ + +#if 0 /* only used to test the powersaving mode, + * if enabled, the drive goes after 5 sec + * in standby mode */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = ide_wait(device, IDE_TIME_OUT); + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, 0); + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, 0xe3); + udelay(50); + c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ +#endif +} + +__weak void ide_led(uchar led, uchar status) +{ +#if defined(CONFIG_IDE_LED) && defined(PER8_BASE) /* required by LED_PORT */ + static uchar led_buffer; /* Buffer for current LED status */ + + uchar *led_port = LED_PORT; + + if (status) /* switch LED on */ + led_buffer |= led; + else /* switch LED off */ + led_buffer &= ~led; + + *led_port = led_buffer; +#endif +} + +__weak void ide_outb(int dev, int port, unsigned char val) +{ + debug("ide_outb (dev= %d, port= 0x%x, val= 0x%02x) : @ 0x%08lx\n", + dev, port, val, + (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); + +#if defined(CONFIG_IDE_AHB) + if (port) { + /* write command */ + ide_write_register(dev, port, val); + } else { + /* write data */ + outb(val, (ATA_CURR_BASE(dev))); + } +#else + outb(val, (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif +} + +__weak unsigned char ide_inb(int dev, int port) +{ + uchar val; + +#if defined(CONFIG_IDE_AHB) + val = ide_read_register(dev, port); +#else + val = inb((ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port))); +#endif + + debug("ide_inb (dev= %d, port= 0x%x) : @ 0x%08lx -> 0x%02x\n", + dev, port, + (ATA_CURR_BASE(dev) + CONFIG_SYS_ATA_PORT_ADDR(port)), val); + return val; +} + +void ide_init(void) +{ + unsigned char c; + int i, bus; + +#ifdef CONFIG_IDE_8xx_PCCARD + extern int ide_devices_found; /* Initialized in check_ide_device() */ +#endif /* CONFIG_IDE_8xx_PCCARD */ + +#ifdef CONFIG_IDE_PREINIT + WATCHDOG_RESET(); + + if (ide_preinit()) { + puts("ide_preinit failed\n"); + return; + } +#endif /* CONFIG_IDE_PREINIT */ + + WATCHDOG_RESET(); + + /* + * Reset the IDE just to be sure. + * Light LED's to show + */ + ide_led((LED_IDE1 | LED_IDE2), 1); /* LED's on */ + + /* ATAPI Drives seems to need a proper IDE Reset */ + ide_reset(); + +#ifdef CONFIG_IDE_INIT_POSTRESET + WATCHDOG_RESET(); + + if (ide_init_postreset()) { + puts("ide_preinit_postreset failed\n"); + return; + } +#endif /* CONFIG_IDE_INIT_POSTRESET */ + + /* + * Wait for IDE to get ready. + * According to spec, this can take up to 31 seconds! + */ + for (bus = 0; bus < CONFIG_SYS_IDE_MAXBUS; ++bus) { + int dev = + bus * (CONFIG_SYS_IDE_MAXDEVICE / + CONFIG_SYS_IDE_MAXBUS); + +#ifdef CONFIG_IDE_8xx_PCCARD + /* Skip non-ide devices from probing */ + if ((ide_devices_found & (1 << bus)) == 0) { + ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + continue; + } +#endif + printf("Bus %d: ", bus); + + ide_bus_ok[bus] = 0; + + /* Select device + */ + udelay(100000); /* 100 ms */ + ide_outb(dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); + udelay(100000); /* 100 ms */ + i = 0; + do { + udelay(10000); /* 10 ms */ + + c = ide_inb(dev, ATA_STATUS); + i++; + if (i > (ATA_RESET_TIME * 100)) { + puts("** Timeout **\n"); + /* LED's off */ + ide_led((LED_IDE1 | LED_IDE2), 0); + return; + } + if ((i >= 100) && ((i % 100) == 0)) + putc('.'); + + } while (c & ATA_STAT_BUSY); + + if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { + puts("not available "); + debug("Status = 0x%02X ", c); +#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ + } else if ((c & ATA_STAT_READY) == 0) { + puts("not available "); + debug("Status = 0x%02X ", c); +#endif + } else { + puts("OK "); + ide_bus_ok[bus] = 1; + } + WATCHDOG_RESET(); + } + + putc('\n'); + + ide_led((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + + for (i = 0; i < CONFIG_SYS_IDE_MAXDEVICE; ++i) { + int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; + ide_dev_desc[i].if_type = IF_TYPE_IDE; + ide_dev_desc[i].devnum = i; + ide_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + ide_dev_desc[i].blksz = 0; + ide_dev_desc[i].log2blksz = + LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); + ide_dev_desc[i].lba = 0; + ide_dev_desc[i].block_read = ide_read; + ide_dev_desc[i].block_write = ide_write; + if (!ide_bus_ok[IDE_BUS(i)]) + continue; + ide_led(led, 1); /* LED on */ + ide_ident(&ide_dev_desc[i]); + ide_led(led, 0); /* LED off */ + dev_print(&ide_dev_desc[i]); + + if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { + /* initialize partition type */ + part_init(&ide_dev_desc[i]); + } + } + WATCHDOG_RESET(); +} + +#ifdef CONFIG_PARTITIONS +struct blk_desc *ide_get_dev(int dev) +{ + return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; +} +#endif + +/* We only need to swap data if we are running on a big endian cpu. */ +#if defined(__LITTLE_ENDIAN) +__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) +{ + ide_input_data(dev, sect_buf, words); +} +#else +__weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) +{ + volatile ushort *pbuf = + (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + ushort *dbuf = (ushort *)sect_buf; + + debug("in input swap data base for read is %lx\n", + (unsigned long) pbuf); + + while (words--) { +#ifdef __MIPS__ + *dbuf++ = swab16p((u16 *)pbuf); + *dbuf++ = swab16p((u16 *)pbuf); +#else + *dbuf++ = ld_le16(pbuf); + *dbuf++ = ld_le16(pbuf); +#endif /* !MIPS */ + } +} +#endif /* __LITTLE_ENDIAN */ + + +#if defined(CONFIG_IDE_SWAP_IO) +__weak void ide_output_data(int dev, const ulong *sect_buf, int words) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + while (words--) { + EIEIO; + *pbuf = *dbuf++; + EIEIO; + *pbuf = *dbuf++; + } +} +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_output_data(int dev, const ulong *sect_buf, int words) +{ +#if defined(CONFIG_IDE_AHB) + ide_write_data(dev, sect_buf, words); +#else + outsw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); +#endif +} +#endif /* CONFIG_IDE_SWAP_IO */ + +#if defined(CONFIG_IDE_SWAP_IO) +__weak void ide_input_data(int dev, ulong *sect_buf, int words) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev) + ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + + debug("in input data base for read is %lx\n", (unsigned long) pbuf); + + while (words--) { + EIEIO; + *dbuf++ = *pbuf; + EIEIO; + *dbuf++ = *pbuf; + } +} +#else /* ! CONFIG_IDE_SWAP_IO */ +__weak void ide_input_data(int dev, ulong *sect_buf, int words) +{ +#if defined(CONFIG_IDE_AHB) + ide_read_data(dev, sect_buf, words); +#else + insw(ATA_CURR_BASE(dev) + ATA_DATA_REG, sect_buf, words << 1); +#endif +} + +#endif /* CONFIG_IDE_SWAP_IO */ + +ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +{ + int device = block_dev->devnum; + ulong n = 0; + unsigned char c; + unsigned char pwrsave = 0; /* power save */ + +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0; + + if (blknr & 0x0000fffff0000000ULL) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; + } +#endif + debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n", + device, blknr, blkcnt, (ulong) buffer); + + ide_led(DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = ide_wait(device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto IDE_READ_E; + } + + /* first check if the drive is in Powersaving mode, if yes, + * increase the timeout value */ + ide_outb(device, ATA_COMMAND, ATA_CMD_CHK_PWR); + udelay(50); + + c = ide_wait(device, IDE_TIME_OUT); /* can't take over 500 ms */ + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto IDE_READ_E; + } + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + printf("No Powersaving mode %X\n", c); + } else { + c = ide_inb(device, ATA_SECT_CNT); + debug("Powersaving %02X\n", c); + if (c == 0) + pwrsave = 1; + } + + + while (blkcnt-- > 0) { + c = ide_wait(device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + break; + } +#ifdef CONFIG_LBA48 + if (lba48) { + /* write high bits */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); +#ifdef CONFIG_SYS_64BIT_LBA + ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); +#else + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); +#endif + } +#endif + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); + ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); + +#ifdef CONFIG_LBA48 + if (lba48) { + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, ATA_CMD_READ_EXT); + + } else +#endif + { + ide_outb(device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); + ide_outb(device, ATA_COMMAND, ATA_CMD_READ); + } + + udelay(50); + + if (pwrsave) { + /* may take up to 4 sec */ + c = ide_wait(device, IDE_SPIN_UP_TIME_OUT); + pwrsave = 0; + } else { + /* can't take over 500 ms */ + c = ide_wait(device, IDE_TIME_OUT); + } + + if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != + ATA_STAT_DRQ) { + printf("Error (no IRQ) dev %d blk " LBAF + ": status %#02x\n", device, blknr, c); + break; + } + + ide_input_data(device, buffer, ATA_SECTORWORDS); + (void) ide_inb(device, ATA_STATUS); /* clear IRQ */ + + ++n; + ++blknr; + buffer += ATA_BLOCKSIZE; + } +IDE_READ_E: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return n; +} + +ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +{ + int device = block_dev->devnum; + ulong n = 0; + unsigned char c; + +#ifdef CONFIG_LBA48 + unsigned char lba48 = 0; + + if (blknr & 0x0000fffff0000000ULL) { + /* more than 28 bits used, use 48bit mode */ + lba48 = 1; + } +#endif + + ide_led(DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + ide_outb(device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + + while (blkcnt-- > 0) { + c = ide_wait(device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf("IDE read: device %d not ready\n", device); + goto WR_OUT; + } +#ifdef CONFIG_LBA48 + if (lba48) { + /* write high bits */ + ide_outb(device, ATA_SECT_CNT, 0); + ide_outb(device, ATA_LBA_LOW, (blknr >> 24) & 0xFF); +#ifdef CONFIG_SYS_64BIT_LBA + ide_outb(device, ATA_LBA_MID, (blknr >> 32) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 40) & 0xFF); +#else + ide_outb(device, ATA_LBA_MID, 0); + ide_outb(device, ATA_LBA_HIGH, 0); +#endif + } +#endif + ide_outb(device, ATA_SECT_CNT, 1); + ide_outb(device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); + ide_outb(device, ATA_LBA_MID, (blknr >> 8) & 0xFF); + ide_outb(device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); + +#ifdef CONFIG_LBA48 + if (lba48) { + ide_outb(device, ATA_DEV_HD, + ATA_LBA | ATA_DEVICE(device)); + ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE_EXT); + + } else +#endif + { + ide_outb(device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | ((blknr >> 24) & 0xF)); + ide_outb(device, ATA_COMMAND, ATA_CMD_WRITE); + } + + udelay(50); + + /* can't take over 500 ms */ + c = ide_wait(device, IDE_TIME_OUT); + + if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) != + ATA_STAT_DRQ) { + printf("Error (no IRQ) dev %d blk " LBAF + ": status %#02x\n", device, blknr, c); + goto WR_OUT; + } + + ide_output_data(device, buffer, ATA_SECTORWORDS); + c = ide_inb(device, ATA_STATUS); /* clear IRQ */ + ++n; + ++blknr; + buffer += ATA_BLOCKSIZE; + } +WR_OUT: + ide_led(DEVICE_LED(device), 0); /* LED off */ + return n; +} + +#if defined(CONFIG_OF_IDE_FIXUP) +int ide_device_present(int dev) +{ + if (dev >= CONFIG_SYS_IDE_MAXBUS) + return 0; + return ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN ? 0 : 1; +} +#endif + +U_BOOT_LEGACY_BLK(ide) = { + .if_typename = "ide", + .if_type = IF_TYPE_IDE, + .max_devs = CONFIG_SYS_IDE_MAXDEVICE, + .desc = ide_dev_desc, +};

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
At present the IDE command code includes both the command-processing code and the core IDE functions and data structures.
Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly.
With this commit:
- Most CONFIG option are referenced from the non-command code
- The concept of a 'current IDE device' is confined to the command code
This will make it easier to convert this code to driver model.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
cmd/ide.c | 1297 +------------------------------------------------------ common/Makefile | 1 + common/ide.c | 1206 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1228 insertions(+), 1276 deletions(-) create mode 100644 common/ide.c
Applied to u-boot-dm.

At present the SATA command code includes both the command-processing code and the core SATA functions and data structures.
Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly.
With this commit: - All CONFIG option are referenced from the non-command code - The concept of a 'current SATA device' is confined to the command code
This will make it easier to convert this code to driver model.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
cmd/sata.c | 138 ++++++++------------------------------------------------ common/Makefile | 1 + common/sata.c | 86 +++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 118 deletions(-) create mode 100644 common/sata.c
diff --git a/cmd/sata.c b/cmd/sata.c index b1a64d9..d18b523 100644 --- a/cmd/sata.c +++ b/cmd/sata.c @@ -16,70 +16,6 @@ #include <sata.h>
static int sata_curr_device = -1; -struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; - -static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, void *dst) -{ - return sata_read(block_dev->devnum, start, blkcnt, dst); -} - -static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, const void *buffer) -{ - return sata_write(block_dev->devnum, start, blkcnt, buffer); -} - -int __sata_initialize(void) -{ - int rc; - int i; - - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) { - memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc)); - sata_dev_desc[i].if_type = IF_TYPE_SATA; - sata_dev_desc[i].devnum = i; - sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - sata_dev_desc[i].type = DEV_TYPE_HARDDISK; - sata_dev_desc[i].lba = 0; - sata_dev_desc[i].blksz = 512; - sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); - sata_dev_desc[i].block_read = sata_bread; - sata_dev_desc[i].block_write = sata_bwrite; - - rc = init_sata(i); - if (!rc) { - rc = scan_sata(i); - if (!rc && (sata_dev_desc[i].lba > 0) && - (sata_dev_desc[i].blksz > 0)) - part_init(&sata_dev_desc[i]); - } - } - sata_curr_device = 0; - return rc; -} -int sata_initialize(void) __attribute__((weak,alias("__sata_initialize"))); - -__weak int __sata_stop(void) -{ - int i, err = 0; - - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) - err |= reset_sata(i); - - if (err) - printf("Could not reset some SATA devices\n"); - - return err; -} -int sata_stop(void) __attribute__((weak, alias("__sata_stop"))); - -#ifdef CONFIG_PARTITIONS -struct blk_desc *sata_get_dev(int dev) -{ - return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL; -} -#endif
static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { @@ -106,70 +42,39 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_USAGE; case 2: if (strncmp(argv[1], "inf", 3) == 0) { - int i; - - putc('\n'); - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; ++i) { - if (sata_dev_desc[i].type == DEV_TYPE_UNKNOWN) - continue; - printf("SATA device %d: ", i); - dev_print(&sata_dev_desc[i]); - } + blk_list_devices(IF_TYPE_SATA); return 0; } else if (strncmp(argv[1], "dev", 3) == 0) { - if (sata_curr_device < 0 || - sata_curr_device >= CONFIG_SYS_SATA_MAX_DEVICE) { - puts("\nno SATA devices available\n"); - return 1; + if (blk_print_device_num(IF_TYPE_SATA, + sata_curr_device)) { + printf("\nno SATA devices available\n"); + return CMD_RET_FAILURE; } - printf("\nSATA device %d: ", sata_curr_device); - dev_print(&sata_dev_desc[sata_curr_device]); return 0; } else if (strncmp(argv[1], "part", 4) == 0) { - int dev, ok; - - for (ok = 0, dev = 0; dev < CONFIG_SYS_SATA_MAX_DEVICE; ++dev) { - if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - ++ok; - if (dev) - putc ('\n'); - part_print(&sata_dev_desc[dev]); - } - } - if (!ok) { + if (blk_list_part(IF_TYPE_SATA)) puts("\nno SATA devices available\n"); - rc ++; - } - return rc; + return 0; } return CMD_RET_USAGE; case 3: if (strncmp(argv[1], "dev", 3) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10);
- printf("\nSATA device %d: ", dev); - if (dev >= CONFIG_SYS_SATA_MAX_DEVICE) { - puts ("unknown device\n"); - return 1; + if (!blk_show_device(IF_TYPE_SATA, dev)) { + sata_curr_device = dev; + printf("... is now current device\n"); + } else { + return CMD_RET_FAILURE; } - dev_print(&sata_dev_desc[dev]); - - if (sata_dev_desc[dev].type == DEV_TYPE_UNKNOWN) - return 1; - - sata_curr_device = dev; - - puts("... is now current device\n"); - return 0; } else if (strncmp(argv[1], "part", 4) == 0) { int dev = (int)simple_strtoul(argv[2], NULL, 10);
- if (sata_dev_desc[dev].part_type != PART_TYPE_UNKNOWN) { - part_print(&sata_dev_desc[dev]); - } else { - printf("\nSATA device %d not available\n", dev); - rc = 1; + if (blk_print_part_devnum(IF_TYPE_SATA, dev)) { + printf("\nSATA device %d not available\n", + dev); + return CMD_RET_FAILURE; } return rc; } @@ -185,11 +90,8 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("\nSATA read: device %d block # %ld, count %ld ... ", sata_curr_device, blk, cnt);
- n = blk_dread(&sata_dev_desc[sata_curr_device], - blk, cnt, (u32 *)addr); - - /* flush cache after read */ - flush_cache(addr, cnt * sata_dev_desc[sata_curr_device].blksz); + n = blk_read_devnum(IF_TYPE_SATA, sata_curr_device, blk, + cnt, (ulong *)addr);
printf("%ld blocks read: %s\n", n, (n==cnt) ? "OK" : "ERROR"); @@ -204,8 +106,8 @@ static int do_sata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("\nSATA write: device %d block # %ld, count %ld ... ", sata_curr_device, blk, cnt);
- n = blk_dwrite(&sata_dev_desc[sata_curr_device], - blk, cnt, (u32 *)addr); + n = blk_write_devnum(IF_TYPE_SATA, sata_curr_device, + blk, cnt, (ulong *)addr);
printf("%ld blocks written: %s\n", n, (n == cnt) ? "OK" : "ERROR"); diff --git a/common/Makefile b/common/Makefile index 1df5add..f9b26b7 100644 --- a/common/Makefile +++ b/common/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o obj-$(CONFIG_LYNXKDI) += lynxkdi.o obj-$(CONFIG_MENU) += menu.o +obj-$(CONFIG_CMD_SATA) += sata.o obj-$(CONFIG_SCSI) += scsi.o obj-$(CONFIG_UPDATE_TFTP) += update.o obj-$(CONFIG_DFU_TFTP) += update.o diff --git a/common/sata.c b/common/sata.c new file mode 100644 index 0000000..1d52fcb --- /dev/null +++ b/common/sata.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2000-2005, DENX Software Engineering + * Wolfgang Denk wd@denx.de + * Copyright (C) Procsys. All rights reserved. + * Mushtaq Khan mushtaq_k@procsys.com + * mushtaqk_921@yahoo.co.in + * Copyright (C) 2008 Freescale Semiconductor, Inc. + * Dave Liu daveliu@freescale.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <sata.h> + +struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; + +#ifdef CONFIG_PARTITIONS +struct blk_desc *sata_get_dev(int dev) +{ + return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL; +} +#endif + +static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start, + lbaint_t blkcnt, void *dst) +{ + return sata_read(block_dev->devnum, start, blkcnt, dst); +} + +static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + return sata_write(block_dev->devnum, start, blkcnt, buffer); +} + +int __sata_initialize(void) +{ + int rc; + int i; + + for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) { + memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc)); + sata_dev_desc[i].if_type = IF_TYPE_SATA; + sata_dev_desc[i].devnum = i; + sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN; + sata_dev_desc[i].type = DEV_TYPE_HARDDISK; + sata_dev_desc[i].lba = 0; + sata_dev_desc[i].blksz = 512; + sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); + sata_dev_desc[i].block_read = sata_bread; + sata_dev_desc[i].block_write = sata_bwrite; + + rc = init_sata(i); + if (!rc) { + rc = scan_sata(i); + if (!rc && sata_dev_desc[i].lba > 0 && + sata_dev_desc[i].blksz > 0) + part_init(&sata_dev_desc[i]); + } + } + + return rc; +} +int sata_initialize(void) __attribute__((weak, alias("__sata_initialize"))); + +__weak int __sata_stop(void) +{ + int i, err = 0; + + for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) + err |= reset_sata(i); + + if (err) + printf("Could not reset some SATA devices\n"); + + return err; +} +int sata_stop(void) __attribute__((weak, alias("__sata_stop"))); + +U_BOOT_LEGACY_BLK(sata) = { + .if_typename = "sata", + .if_type = IF_TYPE_SATA, + .max_devs = CONFIG_SYS_SATA_MAX_DEVICE, + .desc = sata_dev_desc, +};

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
At present the SATA command code includes both the command-processing code and the core SATA functions and data structures.
Separate the latter into its own file, adding functions as needed to avoid the command code accessing data structures directly.
With this commit:
- All CONFIG option are referenced from the non-command code
- The concept of a 'current SATA device' is confined to the command code
This will make it easier to convert this code to driver model.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
cmd/sata.c | 138 ++++++++------------------------------------------------ common/Makefile | 1 + common/sata.c | 86 +++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 118 deletions(-) create mode 100644 common/sata.c
Applied to u-boot-dm.

Instead of calling xx_get_dev() functions for each interface type, use the new legacy block driver which can provide the device through its interface.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
disk/part.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/disk/part.c b/disk/part.c index 2613bff..f055c74 100644 --- a/disk/part.c +++ b/disk/part.c @@ -72,7 +72,6 @@ static struct part_driver *part_driver_lookup_type(int part_type) static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) { const struct block_drvr *drvr = block_drvr; - struct blk_desc* (*reloc_get_dev)(int dev); int (*select_hwpart)(int dev_num, int hwpart); char *name; int ret; @@ -86,16 +85,16 @@ static struct blk_desc *get_dev_hwpart(const char *ifname, int dev, int hwpart) #endif while (drvr->name) { name = drvr->name; - reloc_get_dev = drvr->get_dev; select_hwpart = drvr->select_hwpart; #ifdef CONFIG_NEEDS_MANUAL_RELOC name += gd->reloc_off; - reloc_get_dev += gd->reloc_off; if (select_hwpart) select_hwpart += gd->reloc_off; #endif if (strncmp(ifname, name, strlen(name)) == 0) { - struct blk_desc *dev_desc = reloc_get_dev(dev); + struct blk_desc *dev_desc; + + dev_desc = blk_get_devnum_by_typename(name, dev); if (!dev_desc) return NULL; if (hwpart == 0 && !select_hwpart)

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Instead of calling xx_get_dev() functions for each interface type, use the new legacy block driver which can provide the device through its interface.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
disk/part.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
Applied to u-boot-dm.

This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
board/cm5200/fwupdate.c | 2 +- cmd/usb.c | 16 ++++++++++------ common/spl/spl_usb.c | 2 +- common/usb_storage.c | 17 ----------------- disk/part.c | 2 +- drivers/Makefile | 1 + include/part.h | 2 -- include/usb.h | 1 - 8 files changed, 14 insertions(+), 29 deletions(-)
diff --git a/board/cm5200/fwupdate.c b/board/cm5200/fwupdate.c index 2ed90de..4740c83 100644 --- a/board/cm5200/fwupdate.c +++ b/board/cm5200/fwupdate.c @@ -105,7 +105,7 @@ static int load_rescue_image(ulong addr)
/* Detect storage device */ for (devno = 0; devno < USB_MAX_STOR_DEV; devno++) { - stor_dev = usb_stor_get_dev(devno); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno); if (stor_dev->type != DEV_TYPE_UNKNOWN) break; } diff --git a/cmd/usb.c b/cmd/usb.c index f1a7deb..b83d323 100644 --- a/cmd/usb.c +++ b/cmd/usb.c @@ -723,7 +723,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int devno, ok = 0; if (argc == 2) { for (devno = 0; ; ++devno) { - stor_dev = usb_stor_get_dev(devno); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + devno); if (stor_dev == NULL) break; if (stor_dev->type != DEV_TYPE_UNKNOWN) { @@ -736,7 +737,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } } else { devno = simple_strtoul(argv[2], NULL, 16); - stor_dev = usb_stor_get_dev(devno); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, devno); if (stor_dev != NULL && stor_dev->type != DEV_TYPE_UNKNOWN) { ok++; @@ -762,7 +763,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long n; printf("\nUSB read: device %d block # %ld, count %ld" " ... ", usb_stor_curr_dev, blk, cnt); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + usb_stor_curr_dev); n = blk_dread(stor_dev, blk, cnt, (ulong *)addr); printf("%ld blocks read: %s\n", n, (n == cnt) ? "OK" : "ERROR"); @@ -783,7 +785,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long n; printf("\nUSB write: device %d block # %ld, count %ld" " ... ", usb_stor_curr_dev, blk, cnt); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + usb_stor_curr_dev); n = blk_dwrite(stor_dev, blk, cnt, (ulong *)addr); printf("%ld blocks write: %s\n", n, (n == cnt) ? "OK" : "ERROR"); @@ -796,7 +799,7 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc == 3) { int dev = (int)simple_strtoul(argv[2], NULL, 10); printf("\nUSB device %d: ", dev); - stor_dev = usb_stor_get_dev(dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, dev); if (stor_dev == NULL) { printf("unknown device\n"); return 1; @@ -810,7 +813,8 @@ static int do_usb(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 0; } else { printf("\nUSB device %d: ", usb_stor_curr_dev); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, + usb_stor_curr_dev); dev_print(stor_dev); if (stor_dev->type == DEV_TYPE_UNKNOWN) return 1; diff --git a/common/spl/spl_usb.c b/common/spl/spl_usb.c index c42848e..04fa667 100644 --- a/common/spl/spl_usb.c +++ b/common/spl/spl_usb.c @@ -39,7 +39,7 @@ int spl_usb_load_image(void) #ifdef CONFIG_USB_STORAGE /* try to recognize storage devices immediately */ usb_stor_curr_dev = usb_stor_scan(1); - stor_dev = usb_stor_get_dev(usb_stor_curr_dev); + stor_dev = blk_get_devnum_by_type(IF_TYPE_USB, usb_stor_curr_dev); if (!stor_dev) return -ENODEV; #endif diff --git a/common/usb_storage.c b/common/usb_storage.c index 80bf3db..f2da3a3 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -136,23 +136,6 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr, #endif void uhci_show_temp_int_td(void);
-#ifdef CONFIG_PARTITIONS -struct blk_desc *usb_stor_get_dev(int index) -{ -#ifdef CONFIG_BLK - struct udevice *dev; - int ret; - - ret = blk_get_device(IF_TYPE_USB, index, &dev); - if (ret) - return NULL; - return dev_get_uclass_platdata(dev); -#else - return (index < usb_max_devs) ? &usb_dev_desc[index] : NULL; -#endif -} -#endif - static void usb_show_progress(void) { debug("."); diff --git a/disk/part.c b/disk/part.c index f055c74..1b33928 100644 --- a/disk/part.c +++ b/disk/part.c @@ -32,7 +32,7 @@ const struct block_drvr block_drvr[] = { { .name = "scsi", .get_dev = scsi_get_dev, }, #endif #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) - { .name = "usb", .get_dev = usb_stor_get_dev, }, + { .name = "usb", }, #endif #if defined(CONFIG_MMC) { diff --git a/drivers/Makefile b/drivers/Makefile index 6900097..696b3ac 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -36,6 +36,7 @@ obj-$(CONFIG_SPL_WATCHDOG_SUPPORT) += watchdog/ obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += usb/host/ obj-$(CONFIG_OMAP_USB_PHY) += usb/phy/ obj-$(CONFIG_SPL_SATA_SUPPORT) += block/ +obj-$(CONFIG_SPL_USB_HOST_SUPPORT) += block/
else
diff --git a/include/part.h b/include/part.h index e3811c6..f206910 100644 --- a/include/part.h +++ b/include/part.h @@ -76,7 +76,6 @@ struct blk_desc *blk_get_dev(const char *ifname, int dev); struct blk_desc *ide_get_dev(int dev); struct blk_desc *sata_get_dev(int dev); struct blk_desc *scsi_get_dev(int dev); -struct blk_desc *usb_stor_get_dev(int dev); struct blk_desc *mmc_get_dev(int dev);
/** @@ -178,7 +177,6 @@ static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) static inline struct blk_desc *ide_get_dev(int dev) { return NULL; } static inline struct blk_desc *sata_get_dev(int dev) { return NULL; } static inline struct blk_desc *scsi_get_dev(int dev) { return NULL; } -static inline struct blk_desc *usb_stor_get_dev(int dev) { return NULL; } static inline struct blk_desc *mmc_get_dev(int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } static inline struct blk_desc *systemace_get_dev(int dev) { return NULL; } diff --git a/include/usb.h b/include/usb.h index 5adad36..02a0ccd 100644 --- a/include/usb.h +++ b/include/usb.h @@ -228,7 +228,6 @@ int board_usb_cleanup(int index, enum usb_init_type init); #ifdef CONFIG_USB_STORAGE
#define USB_MAX_STOR_DEV 7 -struct blk_desc *usb_stor_get_dev(int index); int usb_stor_scan(int mode); int usb_stor_info(void);

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
board/cm5200/fwupdate.c | 2 +- cmd/usb.c | 16 ++++++++++------ common/spl/spl_usb.c | 2 +- common/usb_storage.c | 17 ----------------- disk/part.c | 2 +- drivers/Makefile | 1 + include/part.h | 2 -- include/usb.h | 1 - 8 files changed, 14 insertions(+), 29 deletions(-)
Applied to u-boot-dm.

This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/ide.c | 7 ------- disk/part.c | 2 +- include/part.h | 2 -- 3 files changed, 1 insertion(+), 10 deletions(-)
diff --git a/common/ide.c b/common/ide.c index adc1966..5dc90d4 100644 --- a/common/ide.c +++ b/common/ide.c @@ -890,13 +890,6 @@ void ide_init(void) WATCHDOG_RESET(); }
-#ifdef CONFIG_PARTITIONS -struct blk_desc *ide_get_dev(int dev) -{ - return (dev < CONFIG_SYS_IDE_MAXDEVICE) ? &ide_dev_desc[dev] : NULL; -} -#endif - /* We only need to swap data if we are running on a big endian cpu. */ #if defined(__LITTLE_ENDIAN) __weak void ide_input_swap_data(int dev, ulong *sect_buf, int words) diff --git a/disk/part.c b/disk/part.c index 1b33928..bf224b2 100644 --- a/disk/part.c +++ b/disk/part.c @@ -23,7 +23,7 @@
const struct block_drvr block_drvr[] = { #if defined(CONFIG_CMD_IDE) - { .name = "ide", .get_dev = ide_get_dev, }, + { .name = "ide", }, #endif #if defined(CONFIG_CMD_SATA) {.name = "sata", .get_dev = sata_get_dev, }, diff --git a/include/part.h b/include/part.h index f206910..f09b794 100644 --- a/include/part.h +++ b/include/part.h @@ -73,7 +73,6 @@ typedef struct disk_partition { * error occurred. */ struct blk_desc *blk_get_dev(const char *ifname, int dev); -struct blk_desc *ide_get_dev(int dev); struct blk_desc *sata_get_dev(int dev); struct blk_desc *scsi_get_dev(int dev); struct blk_desc *mmc_get_dev(int dev); @@ -174,7 +173,6 @@ extern const struct block_drvr block_drvr[]; #else static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } -static inline struct blk_desc *ide_get_dev(int dev) { return NULL; } static inline struct blk_desc *sata_get_dev(int dev) { return NULL; } static inline struct blk_desc *scsi_get_dev(int dev) { return NULL; } static inline struct blk_desc *mmc_get_dev(int dev) { return NULL; }

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/ide.c | 7 ------- disk/part.c | 2 +- include/part.h | 2 -- 3 files changed, 1 insertion(+), 10 deletions(-)
Applied to u-boot-dm.

This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
cmd/mmc.c | 2 +- disk/part.c | 1 - drivers/mmc/mmc.c | 16 ++-------------- include/part.h | 2 -- 4 files changed, 3 insertions(+), 18 deletions(-)
diff --git a/cmd/mmc.c b/cmd/mmc.c index 39ef072..0fed790 100644 --- a/cmd/mmc.c +++ b/cmd/mmc.c @@ -432,7 +432,7 @@ static int do_mmc_part(cmd_tbl_t *cmdtp, int flag, if (!mmc) return CMD_RET_FAILURE;
- mmc_dev = mmc_get_dev(curr_device); + mmc_dev = blk_get_devnum_by_type(IF_TYPE_MMC, curr_device); if (mmc_dev != NULL && mmc_dev->type != DEV_TYPE_UNKNOWN) { part_print(mmc_dev); return CMD_RET_SUCCESS; diff --git a/disk/part.c b/disk/part.c index bf224b2..e70bef5 100644 --- a/disk/part.c +++ b/disk/part.c @@ -37,7 +37,6 @@ const struct block_drvr block_drvr[] = { #if defined(CONFIG_MMC) { .name = "mmc", - .get_dev = mmc_get_dev, .select_hwpart = mmc_select_hwpart, }, #endif diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 024368c..185d7b2 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1582,7 +1582,7 @@ void mmc_destroy(struct mmc *mmc) free(mmc); }
-static int mmc_get_devp(int dev, struct blk_desc **descp) +static int mmc_get_dev(int dev, struct blk_desc **descp) { struct mmc *mmc = find_mmc_device(dev); int ret; @@ -1598,18 +1598,6 @@ static int mmc_get_devp(int dev, struct blk_desc **descp) return 0; }
-#ifdef CONFIG_PARTITIONS -struct blk_desc *mmc_get_dev(int dev) -{ - struct blk_desc *desc; - - if (mmc_get_devp(dev, &desc)) - return NULL; - - return desc; -} -#endif - /* board-specific MMC power initializations. */ __weak void board_mmc_power_init(void) { @@ -1987,5 +1975,5 @@ U_BOOT_LEGACY_BLK(mmc) = { .if_typename = "mmc", .if_type = IF_TYPE_MMC, .max_devs = -1, - .get_dev = mmc_get_devp, + .get_dev = mmc_get_dev, }; diff --git a/include/part.h b/include/part.h index f09b794..1535930 100644 --- a/include/part.h +++ b/include/part.h @@ -75,7 +75,6 @@ typedef struct disk_partition { struct blk_desc *blk_get_dev(const char *ifname, int dev); struct blk_desc *sata_get_dev(int dev); struct blk_desc *scsi_get_dev(int dev); -struct blk_desc *mmc_get_dev(int dev);
/** * mmc_select_hwpart() - Select the MMC hardware partiion on an MMC device @@ -175,7 +174,6 @@ static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } static inline struct blk_desc *sata_get_dev(int dev) { return NULL; } static inline struct blk_desc *scsi_get_dev(int dev) { return NULL; } -static inline struct blk_desc *mmc_get_dev(int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } static inline struct blk_desc *systemace_get_dev(int dev) { return NULL; } static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; }

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
cmd/mmc.c | 2 +- disk/part.c | 1 - drivers/mmc/mmc.c | 16 ++-------------- include/part.h | 2 -- 4 files changed, 3 insertions(+), 18 deletions(-)
Applied to u-boot-dm.

This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/scsi.c | 7 ------- common/spl/spl_sata.c | 2 +- disk/part.c | 2 +- include/part.h | 2 -- 4 files changed, 2 insertions(+), 11 deletions(-)
diff --git a/common/scsi.c b/common/scsi.c index a336a10..5b6531f 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -327,13 +327,6 @@ void scsi_init(void) } #endif
-#ifdef CONFIG_PARTITIONS -struct blk_desc *scsi_get_dev(int dev) -{ - return (dev < CONFIG_SYS_SCSI_MAX_DEVICE) ? &scsi_dev_desc[dev] : NULL; -} -#endif - /* copy src to dest, skipping leading and trailing blanks * and null terminate the string */ diff --git a/common/spl/spl_sata.c b/common/spl/spl_sata.c index 1719946..9d8cc7c 100644 --- a/common/spl/spl_sata.c +++ b/common/spl/spl_sata.c @@ -34,7 +34,7 @@ int spl_sata_load_image(void) } else { /* try to recognize storage devices immediately */ scsi_scan(0); - stor_dev = scsi_get_dev(0); + stor_dev = blk_get_devnum_by_type(IF_TYPE_SCSI, 0); if (!stor_dev) return -ENODEV; } diff --git a/disk/part.c b/disk/part.c index e70bef5..67cb6c0 100644 --- a/disk/part.c +++ b/disk/part.c @@ -29,7 +29,7 @@ const struct block_drvr block_drvr[] = { {.name = "sata", .get_dev = sata_get_dev, }, #endif #if defined(CONFIG_SCSI) - { .name = "scsi", .get_dev = scsi_get_dev, }, + { .name = "scsi", }, #endif #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) { .name = "usb", }, diff --git a/include/part.h b/include/part.h index 1535930..ecb049f 100644 --- a/include/part.h +++ b/include/part.h @@ -74,7 +74,6 @@ typedef struct disk_partition { */ struct blk_desc *blk_get_dev(const char *ifname, int dev); struct blk_desc *sata_get_dev(int dev); -struct blk_desc *scsi_get_dev(int dev);
/** * mmc_select_hwpart() - Select the MMC hardware partiion on an MMC device @@ -173,7 +172,6 @@ extern const struct block_drvr block_drvr[]; static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } static inline struct blk_desc *sata_get_dev(int dev) { return NULL; } -static inline struct blk_desc *scsi_get_dev(int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } static inline struct blk_desc *systemace_get_dev(int dev) { return NULL; } static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; }

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/scsi.c | 7 ------- common/spl/spl_sata.c | 2 +- disk/part.c | 2 +- include/part.h | 2 -- 4 files changed, 2 insertions(+), 11 deletions(-)
Applied to u-boot-dm.

This function is implemented by the legacy block functions now. Drop it.
We cannot yet make sata_dev_desc[] private to common/sata.c as it is used by the SATA drivers. This will require the SATA interface to be reworked.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
disk/part.c | 2 +- include/part.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/disk/part.c b/disk/part.c index 67cb6c0..4fc774b 100644 --- a/disk/part.c +++ b/disk/part.c @@ -26,7 +26,7 @@ const struct block_drvr block_drvr[] = { { .name = "ide", }, #endif #if defined(CONFIG_CMD_SATA) - {.name = "sata", .get_dev = sata_get_dev, }, + {.name = "sata", }, #endif #if defined(CONFIG_SCSI) { .name = "scsi", }, diff --git a/include/part.h b/include/part.h index ecb049f..74bb5d6 100644 --- a/include/part.h +++ b/include/part.h @@ -73,7 +73,6 @@ typedef struct disk_partition { * error occurred. */ struct blk_desc *blk_get_dev(const char *ifname, int dev); -struct blk_desc *sata_get_dev(int dev);
/** * mmc_select_hwpart() - Select the MMC hardware partiion on an MMC device @@ -171,7 +170,6 @@ extern const struct block_drvr block_drvr[]; #else static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } -static inline struct blk_desc *sata_get_dev(int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } static inline struct blk_desc *systemace_get_dev(int dev) { return NULL; } static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; }

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
This function is implemented by the legacy block functions now. Drop it.
We cannot yet make sata_dev_desc[] private to common/sata.c as it is used by the SATA drivers. This will require the SATA interface to be reworked.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
disk/part.c | 2 +- include/part.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-)
Applied to u-boot-dm.

This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
disk/part.c | 2 +- drivers/block/systemace.c | 14 +++----------- include/part.h | 2 -- include/systemace.h | 7 ------- 4 files changed, 4 insertions(+), 21 deletions(-)
diff --git a/disk/part.c b/disk/part.c index 4fc774b..28c8706 100644 --- a/disk/part.c +++ b/disk/part.c @@ -41,7 +41,7 @@ const struct block_drvr block_drvr[] = { }, #endif #if defined(CONFIG_SYSTEMACE) - { .name = "ace", .get_dev = systemace_get_dev, }, + { .name = "ace", }, #endif #if defined(CONFIG_SANDBOX) { .name = "host", .get_dev = host_get_dev, }, diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index 0d8e26f..4f14d5f 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -104,8 +104,7 @@ static void release_cf_lock(void) ace_writew((val & 0xffff), 0x18); }
-#ifdef CONFIG_PARTITIONS -struct blk_desc *systemace_get_dev(int dev) +static int systemace_get_dev(int dev, struct blk_desc **descp) { /* The first time through this, the systemace_dev object is not yet initialized. In that case, fill it in. */ @@ -127,14 +126,7 @@ struct blk_desc *systemace_get_dev(int dev) part_init(&systemace_dev);
} - - return &systemace_dev; -} -#endif - -static int systemace_get_devp(int dev, struct blk_desc **descp) -{ - *descp = systemace_get_dev(dev); + *descp = &systemace_dev;
return 0; } @@ -269,5 +261,5 @@ U_BOOT_LEGACY_BLK(systemace) = { .if_typename = "ace", .if_type = IF_TYPE_SYSTEMACE, .max_devs = 1, - .get_dev = systemace_get_devp, + .get_dev = systemace_get_dev, }; diff --git a/include/part.h b/include/part.h index 74bb5d6..3b59139 100644 --- a/include/part.h +++ b/include/part.h @@ -91,7 +91,6 @@ struct blk_desc *blk_get_dev(const char *ifname, int dev); * @return 0 if OK, other value for an error */ int mmc_select_hwpart(int dev_num, int hwpart); -struct blk_desc *systemace_get_dev(int dev); struct blk_desc *mg_disk_get_dev(int dev); struct blk_desc *host_get_dev(int dev); int host_get_dev_err(int dev, struct blk_desc **blk_devp); @@ -171,7 +170,6 @@ extern const struct block_drvr block_drvr[]; static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } -static inline struct blk_desc *systemace_get_dev(int dev) { return NULL; } static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } static inline struct blk_desc *host_get_dev(int dev) { return NULL; }
diff --git a/include/systemace.h b/include/systemace.h index 3b6ec7d..bccb2a2 100644 --- a/include/systemace.h +++ b/include/systemace.h @@ -7,11 +7,4 @@ * SPDX-License-Identifier: GPL-2.0+ */
-#ifdef CONFIG_SYSTEMACE - -# include <part.h> - -struct blk_desc *systemace_get_dev(int dev); - -#endif /* CONFIG_SYSTEMACE */ #endif /* __SYSTEMACE_H */

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
disk/part.c | 2 +- drivers/block/systemace.c | 14 +++----------- include/part.h | 2 -- include/systemace.h | 7 ------- 4 files changed, 4 insertions(+), 21 deletions(-)
Applied to u-boot-dm.

This has nothing of consequence. Remove it and its only inclusion site.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/block/systemace.c | 1 - include/systemace.h | 10 ---------- 2 files changed, 11 deletions(-) delete mode 100644 include/systemace.h
diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index 4f14d5f..79e1263 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -27,7 +27,6 @@
#include <common.h> #include <command.h> -#include <systemace.h> #include <part.h> #include <asm/io.h>
diff --git a/include/systemace.h b/include/systemace.h deleted file mode 100644 index bccb2a2..0000000 --- a/include/systemace.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __SYSTEMACE_H -#define __SYSTEMACE_H -/* - * Copyright (c) 2004 Picture Elements, Inc. - * Stephen Williams (steve@picturel.com) - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#endif /* __SYSTEMACE_H */

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
This has nothing of consequence. Remove it and its only inclusion site.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/systemace.c | 1 - include/systemace.h | 10 ---------- 2 files changed, 11 deletions(-) delete mode 100644 include/systemace.h
Applied to u-boot-dm.

This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
disk/part.c | 2 +- drivers/block/sandbox.c | 10 ---------- include/part.h | 2 -- 3 files changed, 1 insertion(+), 13 deletions(-)
diff --git a/disk/part.c b/disk/part.c index 28c8706..e635d90 100644 --- a/disk/part.c +++ b/disk/part.c @@ -44,7 +44,7 @@ const struct block_drvr block_drvr[] = { { .name = "ace", }, #endif #if defined(CONFIG_SANDBOX) - { .name = "host", .get_dev = host_get_dev, }, + { .name = "host", }, #endif { }, }; diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c index 2b6a893..ac28f83 100644 --- a/drivers/block/sandbox.c +++ b/drivers/block/sandbox.c @@ -217,16 +217,6 @@ int host_get_dev_err(int devnum, struct blk_desc **blk_devp) return 0; }
-struct blk_desc *host_get_dev(int dev) -{ - struct blk_desc *blk_dev; - - if (host_get_dev_err(dev, &blk_dev)) - return NULL; - - return blk_dev; -} - #ifdef CONFIG_BLK static const struct blk_ops sandbox_host_blk_ops = { .read = host_block_read, diff --git a/include/part.h b/include/part.h index 3b59139..47f5baf 100644 --- a/include/part.h +++ b/include/part.h @@ -92,7 +92,6 @@ struct blk_desc *blk_get_dev(const char *ifname, int dev); */ int mmc_select_hwpart(int dev_num, int hwpart); struct blk_desc *mg_disk_get_dev(int dev); -struct blk_desc *host_get_dev(int dev); int host_get_dev_err(int dev, struct blk_desc **blk_devp);
/* disk/part.c */ @@ -171,7 +170,6 @@ static inline struct blk_desc *blk_get_dev(const char *ifname, int dev) { return NULL; } static inline int mmc_select_hwpart(int dev_num, int hwpart) { return -1; } static inline struct blk_desc *mg_disk_get_dev(int dev) { return NULL; } -static inline struct blk_desc *host_get_dev(int dev) { return NULL; }
static inline int part_get_info(struct blk_desc *dev_desc, int part, disk_partition_t *info) { return -1; }

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
This function is implemented by the legacy block functions now. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
disk/part.c | 2 +- drivers/block/sandbox.c | 10 ---------- include/part.h | 2 -- 3 files changed, 1 insertion(+), 13 deletions(-)
Applied to u-boot-dm.

This is now handled by the legacy block driver. The get_dev() method is no-longer used. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/part.h | 1 - 1 file changed, 1 deletion(-)
diff --git a/include/part.h b/include/part.h index 47f5baf..bc9dc64 100644 --- a/include/part.h +++ b/include/part.h @@ -12,7 +12,6 @@
struct block_drvr { char *name; - struct blk_desc* (*get_dev)(int dev); int (*select_hwpart)(int dev_num, int hwpart); };

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
This is now handled by the legacy block driver. The get_dev() method is no-longer used. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/part.h | 1 - 1 file changed, 1 deletion(-)
Applied to u-boot-dm.

Add driver-model block-device support to the IDE implementation.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/ide.c | 32 ++++++++++++++++++++++++++++++++ include/ide.h | 8 ++++++++ 2 files changed, 40 insertions(+)
diff --git a/common/ide.c b/common/ide.c index 5dc90d4..ac5b91c 100644 --- a/common/ide.c +++ b/common/ide.c @@ -7,6 +7,7 @@
#include <common.h> #include <ata.h> +#include <dm.h> #include <ide.h> #include <watchdog.h> #include <asm/io.h> @@ -873,8 +874,10 @@ void ide_init(void) ide_dev_desc[i].log2blksz = LOG2_INVALID(typeof(ide_dev_desc[i].log2blksz)); ide_dev_desc[i].lba = 0; +#ifndef CONFIG_BLK ide_dev_desc[i].block_read = ide_read; ide_dev_desc[i].block_write = ide_write; +#endif if (!ide_bus_ok[IDE_BUS(i)]) continue; ide_led(led, 1); /* LED on */ @@ -975,9 +978,17 @@ __weak void ide_input_data(int dev, ulong *sect_buf, int words)
#endif /* CONFIG_IDE_SWAP_IO */
+#ifdef CONFIG_BLK +ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +#else ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer) +#endif { +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#endif int device = block_dev->devnum; ulong n = 0; unsigned char c; @@ -1097,9 +1108,17 @@ IDE_READ_E: return n; }
+#ifdef CONFIG_BLK +ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +#else ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, const void *buffer) +#endif { +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#endif int device = block_dev->devnum; ulong n = 0; unsigned char c; @@ -1191,9 +1210,22 @@ int ide_device_present(int dev) } #endif
+#ifdef CONFIG_BLK +static const struct blk_ops ide_blk_ops = { + .read = ide_read, + .write = ide_write, +}; + +U_BOOT_DRIVER(ide_blk) = { + .name = "ide_blk", + .id = UCLASS_BLK, + .ops = &ide_blk_ops, +}; +#else U_BOOT_LEGACY_BLK(ide) = { .if_typename = "ide", .if_type = IF_TYPE_IDE, .max_devs = CONFIG_SYS_IDE_MAXDEVICE, .desc = ide_dev_desc, }; +#endif diff --git a/include/ide.h b/include/ide.h index a4e65cf..9b0a4a9 100644 --- a/include/ide.h +++ b/include/ide.h @@ -34,10 +34,18 @@ void ide_led(uchar led, uchar status);
void ide_init(void); struct blk_desc; +struct udevice; +#ifdef CONFIG_BLK +ulong ide_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer); +ulong ide_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer); +#else ulong ide_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer); ulong ide_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, const void *buffer); +#endif
#ifdef CONFIG_IDE_PREINIT int ide_preinit(void);

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Add driver-model block-device support to the IDE implementation.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/ide.c | 32 ++++++++++++++++++++++++++++++++ include/ide.h | 8 ++++++++ 2 files changed, 40 insertions(+)
Applied to u-boot-dm.

Enable building the IDE code for sandbox. This is for build coverage only. It does not currently work.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: - Update the commit message to indicate that IDE doesn't work on sandbox
include/configs/sandbox.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 9790a14..a2926fd 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -192,4 +192,14 @@ #define CONFIG_CMD_LZMADEC #define CONFIG_CMD_DATE
+#define CONFIG_CMD_IDE +#define CONFIG_SYS_IDE_MAXBUS 1 +#define CONFIG_SYS_ATA_IDE0_OFFSET 0 +#define CONFIG_SYS_IDE_MAXDEVICE 2 +#define CONFIG_SYS_ATA_BASE_ADDR 0x100 +#define CONFIG_SYS_ATA_DATA_OFFSET 0 +#define CONFIG_SYS_ATA_REG_OFFSET 1 +#define CONFIG_SYS_ATA_ALT_OFFSET 2 +#define CONFIG_SYS_ATA_STRIDE 4 + #endif

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Enable building the IDE code for sandbox. This is for build coverage only. It does not currently work.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2:
- Update the commit message to indicate that IDE doesn't work on sandbox
include/configs/sandbox.h | 10 ++++++++++ 1 file changed, 10 insertions(+)
Applied to u-boot-dm.

Add driver-model block-device support to the SCSI implementation.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/scsi.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
diff --git a/common/scsi.c b/common/scsi.c index 5b6531f..8ac28dd 100644 --- a/common/scsi.c +++ b/common/scsi.c @@ -6,6 +6,7 @@ */
#include <common.h> +#include <dm.h> #include <inttypes.h> #include <pci.h> #include <scsi.h> @@ -149,9 +150,17 @@ void scsi_setup_inquiry(ccb *pccb) pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ }
+#ifdef CONFIG_BLK +static ulong scsi_read(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + void *buffer) +#else static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, void *buffer) +#endif { +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#endif int device = block_dev->devnum; lbaint_t start, blks; uintptr_t buf_addr; @@ -216,9 +225,17 @@ static ulong scsi_read(struct blk_desc *block_dev, lbaint_t blknr, /* Almost the maximum amount of the scsi_ext command.. */ #define SCSI_MAX_WRITE_BLK 0xFFFF
+#ifdef CONFIG_BLK +static ulong scsi_write(struct udevice *dev, lbaint_t blknr, lbaint_t blkcnt, + const void *buffer) +#else static ulong scsi_write(struct blk_desc *block_dev, lbaint_t blknr, lbaint_t blkcnt, const void *buffer) +#endif { +#ifdef CONFIG_BLK + struct blk_desc *block_dev = dev_get_uclass_platdata(dev); +#endif int device = block_dev->devnum; lbaint_t start, blks; uintptr_t buf_addr; @@ -469,8 +486,10 @@ void scsi_scan(int mode) scsi_dev_desc[i].if_type = IF_TYPE_SCSI; scsi_dev_desc[i].devnum = i; scsi_dev_desc[i].part_type = PART_TYPE_UNKNOWN; +#ifndef CONFIG_BLK scsi_dev_desc[i].block_read = scsi_read; scsi_dev_desc[i].block_write = scsi_write; +#endif } scsi_max_devs = 0; for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { @@ -552,9 +571,22 @@ removable: #endif }
+#ifdef CONFIG_BLK +static const struct blk_ops scsi_blk_ops = { + .read = scsi_read, + .write = scsi_write, +}; + +U_BOOT_DRIVER(scsi_blk) = { + .name = "scsi_blk", + .id = UCLASS_BLK, + .ops = &scsi_blk_ops, +}; +#else U_BOOT_LEGACY_BLK(scsi) = { .if_typename = "sata", .if_type = IF_TYPE_SCSI, .max_devs = CONFIG_SYS_SCSI_MAX_DEVICE, .desc = scsi_dev_desc, }; +#endif

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Add driver-model block-device support to the SCSI implementation.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/scsi.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
Applied to u-boot-dm.

Enable building the SCSI code for sandbox. This increases build coverage for sandbox.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/configs/sandbox.h | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index a2926fd..affc9cc 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -202,4 +202,10 @@ #define CONFIG_SYS_ATA_ALT_OFFSET 2 #define CONFIG_SYS_ATA_STRIDE 4
+#define CONFIG_SCSI +#define CONFIG_SCSI_AHCI_PLAT +#define CONFIG_SYS_SCSI_MAX_DEVICE 2 +#define CONFIG_SYS_SCSI_MAX_SCSI_ID 8 +#define CONFIG_SYS_SCSI_MAX_LUN 4 + #endif

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Enable building the SCSI code for sandbox. This increases build coverage for sandbox.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/configs/sandbox.h | 6 ++++++ 1 file changed, 6 insertions(+)
Applied to u-boot-dm.

Add driver-model block-device support to the SATA implementation. This is just a dummy implementation for now, since the SATA low-level API uses numbered devices and that doesn't fit with driver model.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/sata.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-)
diff --git a/common/sata.c b/common/sata.c index 1d52fcb..88f08c9 100644 --- a/common/sata.c +++ b/common/sata.c @@ -11,6 +11,7 @@ */
#include <common.h> +#include <dm.h> #include <sata.h>
struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; @@ -22,6 +23,19 @@ struct blk_desc *sata_get_dev(int dev) } #endif
+#ifdef CONFIG_BLK +static unsigned long sata_bread(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, void *dst) +{ + return -ENOSYS; +} + +static unsigned long sata_bwrite(struct udevice *dev, lbaint_t start, + lbaint_t blkcnt, const void *buffer) +{ + return -ENOSYS; +} +#else static unsigned long sata_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, void *dst) { @@ -33,6 +47,7 @@ static unsigned long sata_bwrite(struct blk_desc *block_dev, lbaint_t start, { return sata_write(block_dev->devnum, start, blkcnt, buffer); } +#endif
int __sata_initialize(void) { @@ -48,9 +63,10 @@ int __sata_initialize(void) sata_dev_desc[i].lba = 0; sata_dev_desc[i].blksz = 512; sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); +#ifndef CONFIG_BLK sata_dev_desc[i].block_read = sata_bread; sata_dev_desc[i].block_write = sata_bwrite; - +#endif rc = init_sata(i); if (!rc) { rc = scan_sata(i); @@ -78,9 +94,22 @@ __weak int __sata_stop(void) } int sata_stop(void) __attribute__((weak, alias("__sata_stop")));
+#ifdef CONFIG_BLK +static const struct blk_ops sata_blk_ops = { + .read = sata_bread, + .write = sata_bwrite, +}; + +U_BOOT_DRIVER(sata_blk) = { + .name = "sata_blk", + .id = UCLASS_BLK, + .ops = &sata_blk_ops, +}; +#else U_BOOT_LEGACY_BLK(sata) = { .if_typename = "sata", .if_type = IF_TYPE_SATA, .max_devs = CONFIG_SYS_SATA_MAX_DEVICE, .desc = sata_dev_desc, }; +#endif

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Add driver-model block-device support to the SATA implementation. This is just a dummy implementation for now, since the SATA low-level API uses numbered devices and that doesn't fit with driver model.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/sata.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-)
Applied to u-boot-dm.

Enable building the SATA code for sandbox. This increases build coverage for sandbox.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/configs/sandbox.h | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index affc9cc..7127611 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -208,4 +208,7 @@ #define CONFIG_SYS_SCSI_MAX_SCSI_ID 8 #define CONFIG_SYS_SCSI_MAX_LUN 4
+#define CONFIG_CMD_SATA +#define CONFIG_SYS_SATA_MAX_DEVICE 2 + #endif

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Enable building the SATA code for sandbox. This increases build coverage for sandbox.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/configs/sandbox.h | 3 +++ 1 file changed, 3 insertions(+)
Applied to u-boot-dm.

Allow a devnum parameter of -1 to indicate that the device number should be alocated automatically. The next highest available device number for that interface type is used.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/block/blk-uclass.c | 29 +++++++++++++++++++++++++++++ include/blk.h | 15 ++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index 3687b9a..c947d95 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -411,6 +411,26 @@ int blk_prepare_device(struct udevice *dev) return 0; }
+int blk_find_max_devnum(enum if_type if_type) +{ + struct udevice *dev; + int max_devnum = -ENODEV; + struct uclass *uc; + int ret; + + ret = uclass_get(UCLASS_BLK, &uc); + if (ret) + return ret; + uclass_foreach_dev(dev, uc) { + struct blk_desc *desc = dev_get_uclass_platdata(dev); + + if (desc->if_type == if_type && desc->devnum > max_devnum) + max_devnum = desc->devnum; + } + + return max_devnum; +} + int blk_create_device(struct udevice *parent, const char *drv_name, const char *name, int if_type, int devnum, int blksz, lbaint_t size, struct udevice **devp) @@ -428,6 +448,15 @@ int blk_create_device(struct udevice *parent, const char *drv_name, desc->lba = size / blksz; desc->part_type = PART_TYPE_UNKNOWN; desc->bdev = dev; + if (devnum == -1) { + ret = blk_find_max_devnum(if_type); + if (ret == -ENODEV) + devnum = 0; + else if (ret < 0) + return ret; + else + devnum = ret + 1; + } desc->devnum = devnum; *devp = dev;
diff --git a/include/blk.h b/include/blk.h index 2caac9c..547c3b4 100644 --- a/include/blk.h +++ b/include/blk.h @@ -270,7 +270,8 @@ int blk_next_device(struct udevice **devp); * @drv_name: Driver name to use for the block device * @name: Name for the device * @if_type: Interface type (enum if_type_t) - * @devnum: Device number, specific to the interface type + * @devnum: Device number, specific to the interface type, or -1 to + * allocate the next available number * @blksz: Block size of the device in bytes (typically 512) * @size: Total size of the device in bytes * @devp: the new device (which has not been probed) @@ -299,6 +300,18 @@ int blk_prepare_device(struct udevice *dev); */ int blk_unbind_all(int if_type);
+/** + * blk_find_max_devnum() - find the maximum device number for an interface type + * + * Finds the last allocated device number for an interface type @if_type. The + * next number is safe to use for a newly allocated device. + * + * @if_type: Interface type to scan + * @return maximum device number found, or -ENODEV if none, or other -ve on + * error + */ +int blk_find_max_devnum(enum if_type if_type); + #else #include <errno.h> /*

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Allow a devnum parameter of -1 to indicate that the device number should be alocated automatically. The next highest available device number for that interface type is used.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/blk-uclass.c | 29 +++++++++++++++++++++++++++++ include/blk.h | 15 ++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-)
Applied to u-boot-dm.

Add a function that automatically builds the device name given the parent and a supplied string. Most callers will want to do this, so putting this functionality in one place makes more sense.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
common/usb_storage.c | 13 +++++-------- drivers/block/blk-uclass.c | 15 +++++++++++++++ include/blk.h | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/common/usb_storage.c b/common/usb_storage.c index f2da3a3..7e6e52d 100644 --- a/common/usb_storage.c +++ b/common/usb_storage.c @@ -200,7 +200,6 @@ static int usb_stor_probe_device(struct usb_device *udev)
#ifdef CONFIG_BLK struct us_data *data; - char dev_name[30], *str; int ret; #else int start; @@ -223,14 +222,12 @@ static int usb_stor_probe_device(struct usb_device *udev) for (lun = 0; lun <= max_lun; lun++) { struct blk_desc *blkdev; struct udevice *dev; + char str[10];
- snprintf(dev_name, sizeof(dev_name), "%s.lun%d", - udev->dev->name, lun); - str = strdup(dev_name); - if (!str) - return -ENOMEM; - ret = blk_create_device(udev->dev, "usb_storage_blk", str, - IF_TYPE_USB, usb_max_devs, 512, 0, &dev); + snprintf(str, sizeof(str), "lun%d", lun); + ret = blk_create_devicef(udev->dev, "usb_storage_blk", str, + IF_TYPE_USB, usb_max_devs, 512, 0, + &dev); if (ret) { debug("Cannot bind driver\n"); return ret; diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index c947d95..6ecbff0 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -463,6 +463,21 @@ int blk_create_device(struct udevice *parent, const char *drv_name, return 0; }
+int blk_create_devicef(struct udevice *parent, const char *drv_name, + const char *name, int if_type, int devnum, int blksz, + lbaint_t size, struct udevice **devp) +{ + char dev_name[30], *str; + + snprintf(dev_name, sizeof(dev_name), "%s.%s", parent->name, name); + str = strdup(dev_name); + if (!str) + return -ENOMEM; + + return blk_create_device(parent, drv_name, str, if_type, devnum, + blksz, size, devp); +} + int blk_unbind_all(int if_type) { struct uclass *uc; diff --git a/include/blk.h b/include/blk.h index 547c3b4..82b2c1a 100644 --- a/include/blk.h +++ b/include/blk.h @@ -281,6 +281,23 @@ int blk_create_device(struct udevice *parent, const char *drv_name, lbaint_t size, struct udevice **devp);
/** + * blk_create_devicef() - Create a new named block device + * + * @parent: Parent of the new device + * @drv_name: Driver name to use for the block device + * @name: Name for the device (parent name is prepended) + * @if_type: Interface type (enum if_type_t) + * @devnum: Device number, specific to the interface type, or -1 to + * allocate the next available number + * @blksz: Block size of the device in bytes (typically 512) + * @size: Total size of the device in bytes + * @devp: the new device (which has not been probed) + */ +int blk_create_devicef(struct udevice *parent, const char *drv_name, + const char *name, int if_type, int devnum, int blksz, + lbaint_t size, struct udevice **devp); + +/** * blk_prepare_device() - Prepare a block device for use * * This reads partition information from the device if supported.

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Add a function that automatically builds the device name given the parent and a supplied string. Most callers will want to do this, so putting this functionality in one place makes more sense.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
common/usb_storage.c | 13 +++++-------- drivers/block/blk-uclass.c | 15 +++++++++++++++ include/blk.h | 17 +++++++++++++++++ 3 files changed, 37 insertions(+), 8 deletions(-)
Applied to u-boot-dm.

Move the systemace_get_dev() function below systemace_read() so that we can avoid a forward declaration.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/block/systemace.c | 57 +++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 31 deletions(-)
diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index 79e1263..eeba7f0 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -68,10 +68,6 @@ static u16 ace_readw(unsigned off) return in16(base + off); }
-static unsigned long systemace_read(struct blk_desc *block_dev, - unsigned long start, lbaint_t blkcnt, - void *buffer); - static struct blk_desc systemace_dev = { 0 };
static int get_cf_lock(void) @@ -103,33 +99,6 @@ static void release_cf_lock(void) ace_writew((val & 0xffff), 0x18); }
-static int systemace_get_dev(int dev, struct blk_desc **descp) -{ - /* The first time through this, the systemace_dev object is - not yet initialized. In that case, fill it in. */ - if (systemace_dev.blksz == 0) { - systemace_dev.if_type = IF_TYPE_UNKNOWN; - systemace_dev.devnum = 0; - systemace_dev.part_type = PART_TYPE_UNKNOWN; - systemace_dev.type = DEV_TYPE_HARDDISK; - systemace_dev.blksz = 512; - systemace_dev.log2blksz = LOG2(systemace_dev.blksz); - systemace_dev.removable = 1; - systemace_dev.block_read = systemace_read; - - /* - * Ensure the correct bus mode (8/16 bits) gets enabled - */ - ace_writew(width == 8 ? 0 : 0x0001, 0); - - part_init(&systemace_dev); - - } - *descp = &systemace_dev; - - return 0; -} - /* * This function is called (by dereferencing the block_read pointer in * the dev_desc) to read blocks of data. The return value is the @@ -256,6 +225,32 @@ static unsigned long systemace_read(struct blk_desc *block_dev, return blkcnt; }
+static int systemace_get_dev(int dev, struct blk_desc **descp) +{ + /* The first time through this, the systemace_dev object is + not yet initialized. In that case, fill it in. */ + if (systemace_dev.blksz == 0) { + systemace_dev.if_type = IF_TYPE_UNKNOWN; + systemace_dev.devnum = 0; + systemace_dev.part_type = PART_TYPE_UNKNOWN; + systemace_dev.type = DEV_TYPE_HARDDISK; + systemace_dev.blksz = 512; + systemace_dev.log2blksz = LOG2(systemace_dev.blksz); + systemace_dev.removable = 1; + systemace_dev.block_read = systemace_read; + + /* + * Ensure the correct bus mode (8/16 bits) gets enabled + */ + ace_writew(width == 8 ? 0 : 0x0001, 0); + + part_init(&systemace_dev); + } + *descp = &systemace_dev; + + return 0; +} + U_BOOT_LEGACY_BLK(systemace) = { .if_typename = "ace", .if_type = IF_TYPE_SYSTEMACE,

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Move the systemace_get_dev() function below systemace_read() so that we can avoid a forward declaration.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/systemace.c | 57 +++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 31 deletions(-)
Applied to u-boot-dm.

Add support for CONFIG_BLK to the systemace driver.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
drivers/block/systemace.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/drivers/block/systemace.c b/drivers/block/systemace.c index eeba7f0..9392bea 100644 --- a/drivers/block/systemace.c +++ b/drivers/block/systemace.c @@ -27,6 +27,7 @@
#include <common.h> #include <command.h> +#include <dm.h> #include <part.h> #include <asm/io.h>
@@ -68,7 +69,9 @@ static u16 ace_readw(unsigned off) return in16(base + off); }
+#ifndef CONFIG_BLK static struct blk_desc systemace_dev = { 0 }; +#endif
static int get_cf_lock(void) { @@ -104,9 +107,14 @@ static void release_cf_lock(void) * the dev_desc) to read blocks of data. The return value is the * number of blocks read. A zero return indicates an error. */ +#ifdef CONFIG_BLK +static unsigned long systemace_read(struct udevice *dev, unsigned long start, + lbaint_t blkcnt, void *buffer) +#else static unsigned long systemace_read(struct blk_desc *block_dev, unsigned long start, lbaint_t blkcnt, void *buffer) +#endif { int retry; unsigned blk_countdown; @@ -225,6 +233,41 @@ static unsigned long systemace_read(struct blk_desc *block_dev, return blkcnt; }
+#ifdef CONFIG_BLK +static int systemace_bind(struct udevice *dev) +{ + struct blk_desc *bdesc; + struct udevice *bdev; + int ret; + + ret = blk_create_devicef(dev, "systemace_blk", "blk", IF_TYPE_SYSTEMACE, + -1, 512, 0, &bdev); + if (ret) { + debug("Cannot create block device\n"); + return ret; + } + bdesc = dev_get_uclass_platdata(bdev); + bdesc->removable = 1; + bdesc->part_type = PART_TYPE_UNKNOWN; + bdesc->log2blksz = LOG2(bdesc->blksz); + + /* Ensure the correct bus mode (8/16 bits) gets enabled */ + ace_writew(width == 8 ? 0 : 0x0001, 0); + + return 0; +} + +static const struct blk_ops systemace_blk_ops = { + .read = systemace_read, +}; + +U_BOOT_DRIVER(systemace_blk) = { + .name = "systemace_blk", + .id = UCLASS_BLK, + .ops = &systemace_blk_ops, + .bind = systemace_bind, +}; +#else static int systemace_get_dev(int dev, struct blk_desc **descp) { /* The first time through this, the systemace_dev object is @@ -257,3 +300,4 @@ U_BOOT_LEGACY_BLK(systemace) = { .max_devs = 1, .get_dev = systemace_get_dev, }; +#endif

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Add support for CONFIG_BLK to the systemace driver.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
drivers/block/systemace.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+)
Applied to u-boot-dm.

Enable building the systemace code for sandbox. This increases build coverage for sandbox.
Signed-off-by: Simon Glass sjg@chromium.org ---
Changes in v2: None
include/configs/sandbox.h | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 7127611..c51d4cd 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -211,4 +211,8 @@ #define CONFIG_CMD_SATA #define CONFIG_SYS_SATA_MAX_DEVICE 2
+#define CONFIG_SYSTEMACE +#define CONFIG_SYS_SYSTEMACE_WIDTH 16 +#define CONFIG_SYS_SYSTEMACE_BASE 0 + #endif

On 1 May 2016 at 11:36, Simon Glass sjg@chromium.org wrote:
Enable building the systemace code for sandbox. This increases build coverage for sandbox.
Signed-off-by: Simon Glass sjg@chromium.org
Changes in v2: None
include/configs/sandbox.h | 4 ++++ 1 file changed, 4 insertions(+)
Applied to u-boot-dm.

Hi,
On 1 May 2016 at 11:35, Simon Glass sjg@chromium.org wrote:
This series adjusts the block device code to support conversion to driver model. Specifically
- A new 'legacy' block interface is created, allowing block devices to be
defined by a linker list and accessed through function calls
- Block device commands (such as sata and scsi) are adjusted to use these
functions rather than the block device array directly
- These same function calls are then implemented by the block uclass
- The existing block-device table in part.c is dropped
- The opportunity is taken to clean up the code style, as block devices are
one of the few remaining dark corners in U-Boot
It is useful to enable all block device drivers with sandbox. This improves sandbox code coverage and allows tests to be written. The following are enabled by this series:
- IDE
- SCSI
- SATA
- Systemace
USB was already enabled. MMC will be enabled by a future series. Note that these devices do not actually function in sandbox, but the code is compiled.
As mentioned, future work will enable MMC for sandbox including adding rudimentary sandbox SD card emulation. It would also be possible to create emulations for IDE, SCSI, SATA and Systemace but that work is not planned.
It should be noted that the current CONFIG_DM_MMC option does not fully enable driver model for MMC, since the MMC operations are not running through driver model. This will need to be addressed at some point.
This series is available at u-boot-dm/blka-working
I'd like to apply this series in the next few days - please let me know if there are any more comments.
Regards, Simon
participants (2)
-
Simon Glass
-
Tom Rini