From 9bf033dd667a85d0f8ca84084bdf518b44bdb4bc Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Wed, 13 Nov 2024 07:47:36 -0500 Subject: [PATCH] ata: Prefer using "virtual" sector size where possible Normally, if a device uses larger physical sector size than the logical size and supports so-called "512e" mode, we let the device deal with partial sector reads/writes. However, if MAX_VIRT_SECTOR_SIZE is defined, we support partitioning/filesystems that use a larger "virtual" sector than the logical sector. typically this matches the physical sector size of the drive, which means that despite a small logical sector size, all I/O is done in terms of the physical sector size. Therefore, when MAX_VIRT_SECTOR_SIZE and MAX_PHYS_SECTOR_SIZE are enabled (currently only ipod5g and ipod6g), prefer software-based partial sector I/O. Change-Id: I0815ad0a2f987b89bb2debfbf3d0ed64cdf85525 --- firmware/common/disk.c | 5 +++++ firmware/drivers/ata-common.c | 15 +++++++++++++++ firmware/export/ata.h | 4 ++++ 3 files changed, 24 insertions(+) diff --git a/firmware/common/disk.c b/firmware/common/disk.c index e681fb64e3..d409c68ee1 100644 --- a/firmware/common/disk.c +++ b/firmware/common/disk.c @@ -434,6 +434,11 @@ int disk_mount(int drive) } #endif /* MAX_VIRT_SECTOR_SIZE */ } + +#if defined(MAX_VIRT_SECTOR_SIZE) && defined(MAX_PHYS_SECTOR_SIZE) + if (mounted) + ata_set_phys_sector_mult(disk_sector_multiplier[drive]); +#endif } disk_writer_unlock(); diff --git a/firmware/drivers/ata-common.c b/firmware/drivers/ata-common.c index 016c93967a..3a1cea2dca 100644 --- a/firmware/drivers/ata-common.c +++ b/firmware/drivers/ata-common.c @@ -238,6 +238,10 @@ static int ata_get_phys_sector_mult(void) /* Check if drive really needs emulation - if we can access sector 1 then assume the drive supports "512e" and will handle it better than us, so ignore the large physical sectors. + + The exception here is if the device is partitioned to use + larger-than-logical "virtual" sectors; in that case we will + use whichever one (ie physical/"virtual") is larger. */ char throwaway[__MAX_VARIABLE_LOG_SECTOR]; rc = ata_transfer_sectors(1, 1, &throwaway, false); @@ -254,4 +258,15 @@ static int ata_get_phys_sector_mult(void) return 0; } +void ata_set_phys_sector_mult(unsigned int mult) +{ + unsigned int max = MAX_PHYS_SECTOR_SIZE/log_sector_size; + /* virtual sector could be larger than pyhsical sector */ + if (!mult || mult > max) + mult = max; + /* It needs to be at _least_ the size of the real multiplier */ + if (mult > phys_sector_mult) + phys_sector_mult = mult; +} + #endif /* MAX_PHYS_SECTOR_SIZE */ diff --git a/firmware/export/ata.h b/firmware/export/ata.h index dfa73eebf5..f29c052be3 100644 --- a/firmware/export/ata.h +++ b/firmware/export/ata.h @@ -235,4 +235,8 @@ int ata_read_smart(struct ata_smart_values*); #define ATA_IDENTIFY_WORDS 256 +#ifdef MAX_PHYS_SECTOR_SIZE +void ata_set_phys_sector_mult(unsigned int mult); +#endif + #endif /* __ATA_H__ */