aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-11-19 21:15:47 -0500
committerTejun Heo <htejun@gmail.com>2006-12-03 03:56:23 -0500
commit6a36261e63770ab61422550b774fe949ccca5fa9 (patch)
tree2bbd8271e01f933c6395fb1b836269ab939fca34 /drivers/ata
parent3d3cca37559e3ab2b574eda11ed5207ccdb8980a (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.c81
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
2162unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf, 2177unsigned 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;