diff options
author | Tejun Heo <htejun@gmail.com> | 2006-11-19 21:15:47 -0500 |
---|---|---|
committer | Tejun Heo <htejun@gmail.com> | 2006-12-03 03:56:23 -0500 |
commit | 6a36261e63770ab61422550b774fe949ccca5fa9 (patch) | |
tree | 2bbd8271e01f933c6395fb1b836269ab939fca34 /drivers/ata | |
parent | 3d3cca37559e3ab2b574eda11ed5207ccdb8980a (diff) |
[PATCH] libata: fix READ CAPACITY simulation
* READ CAPACITY (16) implementation fixed. Result was shifted by two
bytes. Carlos Pardo spotted this problem and submitted preliminary
patch. Capacity => 2TB is handled correctly now. (verifid w/ fake
capacity)
* Use dev->n_sectors instead of re-reading directly from ID data.
* Define and use ATA_SCSI_RBUF_SET() which considers rbuf length.
This should be done for all simulation functions. Userland can
issue any simulated command with arbitrary buffer length.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Cc: Carlos Pardo <Carlos.Pardo@siliconimage.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-scsi.c | 81 |
1 files changed, 36 insertions, 45 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 56d7e1ea9d72..7ff1adfc729c 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
@@ -1698,6 +1698,22 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args, | |||
1698 | } | 1698 | } |
1699 | 1699 | ||
1700 | /** | 1700 | /** |
1701 | * ATA_SCSI_RBUF_SET - helper to set values in SCSI response buffer | ||
1702 | * @idx: byte index into SCSI response buffer | ||
1703 | * @val: value to set | ||
1704 | * | ||
1705 | * To be used by SCSI command simulator functions. This macros | ||
1706 | * expects two local variables, u8 *rbuf and unsigned int buflen, | ||
1707 | * are in scope. | ||
1708 | * | ||
1709 | * LOCKING: | ||
1710 | * None. | ||
1711 | */ | ||
1712 | #define ATA_SCSI_RBUF_SET(idx, val) do { \ | ||
1713 | if ((idx) < buflen) rbuf[(idx)] = (u8)(val); \ | ||
1714 | } while (0) | ||
1715 | |||
1716 | /** | ||
1701 | * ata_scsiop_inq_std - Simulate INQUIRY command | 1717 | * ata_scsiop_inq_std - Simulate INQUIRY command |
1702 | * @args: device IDENTIFY data / SCSI command of interest. | 1718 | * @args: device IDENTIFY data / SCSI command of interest. |
1703 | * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. | 1719 | * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. |
@@ -2156,67 +2172,42 @@ saving_not_supp: | |||
2156 | * Simulate READ CAPACITY commands. | 2172 | * Simulate READ CAPACITY commands. |
2157 | * | 2173 | * |
2158 | * LOCKING: | 2174 | * LOCKING: |
2159 | * spin_lock_irqsave(host lock) | 2175 | * None. |
2160 | */ | 2176 | */ |
2161 | |||
2162 | unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, | 2177 | unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, |
2163 | unsigned int buflen) | 2178 | unsigned int buflen) |
2164 | { | 2179 | { |
2165 | u64 n_sectors; | 2180 | u64 last_lba = args->dev->n_sectors - 1; /* LBA of the last block */ |
2166 | u32 tmp; | ||
2167 | 2181 | ||
2168 | VPRINTK("ENTER\n"); | 2182 | VPRINTK("ENTER\n"); |
2169 | 2183 | ||
2170 | if (ata_id_has_lba(args->id)) { | ||
2171 | if (ata_id_has_lba48(args->id)) | ||
2172 | n_sectors = ata_id_u64(args->id, 100); | ||
2173 | else | ||
2174 | n_sectors = ata_id_u32(args->id, 60); | ||
2175 | } else { | ||
2176 | /* CHS default translation */ | ||
2177 | n_sectors = args->id[1] * args->id[3] * args->id[6]; | ||
2178 | |||
2179 | if (ata_id_current_chs_valid(args->id)) | ||
2180 | /* CHS current translation */ | ||
2181 | n_sectors = ata_id_u32(args->id, 57); | ||
2182 | } | ||
2183 | |||
2184 | n_sectors--; /* ATA TotalUserSectors - 1 */ | ||
2185 | |||
2186 | if (args->cmd->cmnd[0] == READ_CAPACITY) { | 2184 | if (args->cmd->cmnd[0] == READ_CAPACITY) { |
2187 | if( n_sectors >= 0xffffffffULL ) | 2185 | if (last_lba >= 0xffffffffULL) |
2188 | tmp = 0xffffffff ; /* Return max count on overflow */ | 2186 | last_lba = 0xffffffff; |
2189 | else | ||
2190 | tmp = n_sectors ; | ||
2191 | 2187 | ||
2192 | /* sector count, 32-bit */ | 2188 | /* sector count, 32-bit */ |
2193 | rbuf[0] = tmp >> (8 * 3); | 2189 | ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 3)); |
2194 | rbuf[1] = tmp >> (8 * 2); | 2190 | ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 2)); |
2195 | rbuf[2] = tmp >> (8 * 1); | 2191 | ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 1)); |
2196 | rbuf[3] = tmp; | 2192 | ATA_SCSI_RBUF_SET(3, last_lba); |
2197 | 2193 | ||
2198 | /* sector size */ | 2194 | /* sector size */ |
2199 | tmp = ATA_SECT_SIZE; | 2195 | ATA_SCSI_RBUF_SET(6, ATA_SECT_SIZE >> 8); |
2200 | rbuf[6] = tmp >> 8; | 2196 | ATA_SCSI_RBUF_SET(7, ATA_SECT_SIZE); |
2201 | rbuf[7] = tmp; | ||
2202 | |||
2203 | } else { | 2197 | } else { |
2204 | /* sector count, 64-bit */ | 2198 | /* sector count, 64-bit */ |
2205 | tmp = n_sectors >> (8 * 4); | 2199 | ATA_SCSI_RBUF_SET(0, last_lba >> (8 * 7)); |
2206 | rbuf[2] = tmp >> (8 * 3); | 2200 | ATA_SCSI_RBUF_SET(1, last_lba >> (8 * 6)); |
2207 | rbuf[3] = tmp >> (8 * 2); | 2201 | ATA_SCSI_RBUF_SET(2, last_lba >> (8 * 5)); |
2208 | rbuf[4] = tmp >> (8 * 1); | 2202 | ATA_SCSI_RBUF_SET(3, last_lba >> (8 * 4)); |
2209 | rbuf[5] = tmp; | 2203 | ATA_SCSI_RBUF_SET(4, last_lba >> (8 * 3)); |
2210 | tmp = n_sectors; | 2204 | ATA_SCSI_RBUF_SET(5, last_lba >> (8 * 2)); |
2211 | rbuf[6] = tmp >> (8 * 3); | 2205 | ATA_SCSI_RBUF_SET(6, last_lba >> (8 * 1)); |
2212 | rbuf[7] = tmp >> (8 * 2); | 2206 | ATA_SCSI_RBUF_SET(7, last_lba); |
2213 | rbuf[8] = tmp >> (8 * 1); | ||
2214 | rbuf[9] = tmp; | ||
2215 | 2207 | ||
2216 | /* sector size */ | 2208 | /* sector size */ |
2217 | tmp = ATA_SECT_SIZE; | 2209 | ATA_SCSI_RBUF_SET(10, ATA_SECT_SIZE >> 8); |
2218 | rbuf[12] = tmp >> 8; | 2210 | ATA_SCSI_RBUF_SET(11, ATA_SECT_SIZE); |
2219 | rbuf[13] = tmp; | ||
2220 | } | 2211 | } |
2221 | 2212 | ||
2222 | return 0; | 2213 | return 0; |