Skip to content

Commit

Permalink
[libata scsi] tidy up SCSI lba and xfer len calculations
Browse files Browse the repository at this point in the history
move the redundant SCSI lba and transfer length calculation code from
ata_scsi_verify_xlat() and ata_scsi_rw_xlat() to common functions.
  • Loading branch information
Albert Lee authored and Jeff Garzik committed Oct 4, 2005
1 parent c187c4b commit 3aef523
Showing 1 changed file with 115 additions and 64 deletions.
179 changes: 115 additions & 64 deletions drivers/scsi/libata-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,99 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
return 0;
}

/**
* scsi_6_lba_len - Get LBA and transfer length
* @scsicmd: SCSI command to translate
*
* Calculate LBA and transfer length for 6-byte commands.
*
* RETURNS:
* @plba: the LBA
* @plen: the transfer length
*/

static void scsi_6_lba_len(u8 *scsicmd, u64 *plba, u32 *plen)
{
u64 lba = 0;
u32 len = 0;

VPRINTK("six-byte command\n");

lba |= ((u64)scsicmd[2]) << 8;
lba |= ((u64)scsicmd[3]);

len |= ((u32)scsicmd[4]);

*plba = lba;
*plen = len;
}

/**
* scsi_10_lba_len - Get LBA and transfer length
* @scsicmd: SCSI command to translate
*
* Calculate LBA and transfer length for 10-byte commands.
*
* RETURNS:
* @plba: the LBA
* @plen: the transfer length
*/

static void scsi_10_lba_len(u8 *scsicmd, u64 *plba, u32 *plen)
{
u64 lba = 0;
u32 len = 0;

VPRINTK("ten-byte command\n");

lba |= ((u64)scsicmd[2]) << 24;
lba |= ((u64)scsicmd[3]) << 16;
lba |= ((u64)scsicmd[4]) << 8;
lba |= ((u64)scsicmd[5]);

len |= ((u32)scsicmd[7]) << 8;
len |= ((u32)scsicmd[8]);

*plba = lba;
*plen = len;
}

/**
* scsi_16_lba_len - Get LBA and transfer length
* @scsicmd: SCSI command to translate
*
* Calculate LBA and transfer length for 16-byte commands.
*
* RETURNS:
* @plba: the LBA
* @plen: the transfer length
*/

static void scsi_16_lba_len(u8 *scsicmd, u64 *plba, u32 *plen)
{
u64 lba = 0;
u32 len = 0;

VPRINTK("sixteen-byte command\n");

lba |= ((u64)scsicmd[2]) << 56;
lba |= ((u64)scsicmd[3]) << 48;
lba |= ((u64)scsicmd[4]) << 40;
lba |= ((u64)scsicmd[5]) << 32;
lba |= ((u64)scsicmd[6]) << 24;
lba |= ((u64)scsicmd[7]) << 16;
lba |= ((u64)scsicmd[8]) << 8;
lba |= ((u64)scsicmd[9]);

len |= ((u32)scsicmd[10]) << 24;
len |= ((u32)scsicmd[11]) << 16;
len |= ((u32)scsicmd[12]) << 8;
len |= ((u32)scsicmd[13]);

*plba = lba;
*plen = len;
}

/**
* ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
* @qc: Storage for translated ATA taskfile
Expand All @@ -508,38 +601,16 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
unsigned int lba = tf->flags & ATA_TFLAG_LBA;
unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
u64 dev_sectors = qc->dev->n_sectors;
u64 block = 0;
u32 n_block = 0;
u64 block;
u32 n_block;

tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf->protocol = ATA_PROT_NODATA;

if (scsicmd[0] == VERIFY) {
block |= ((u64)scsicmd[2]) << 24;
block |= ((u64)scsicmd[3]) << 16;
block |= ((u64)scsicmd[4]) << 8;
block |= ((u64)scsicmd[5]);

n_block |= ((u32)scsicmd[7]) << 8;
n_block |= ((u32)scsicmd[8]);
}

else if (scsicmd[0] == VERIFY_16) {
block |= ((u64)scsicmd[2]) << 56;
block |= ((u64)scsicmd[3]) << 48;
block |= ((u64)scsicmd[4]) << 40;
block |= ((u64)scsicmd[5]) << 32;
block |= ((u64)scsicmd[6]) << 24;
block |= ((u64)scsicmd[7]) << 16;
block |= ((u64)scsicmd[8]) << 8;
block |= ((u64)scsicmd[9]);

n_block |= ((u32)scsicmd[10]) << 24;
n_block |= ((u32)scsicmd[11]) << 16;
n_block |= ((u32)scsicmd[12]) << 8;
n_block |= ((u32)scsicmd[13]);
}

if (scsicmd[0] == VERIFY)
scsi_10_lba_len(scsicmd, &block, &n_block);
else if (scsicmd[0] == VERIFY_16)
scsi_16_lba_len(scsicmd, &block, &n_block);
else
return 1;

Expand Down Expand Up @@ -636,8 +707,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
struct ata_device *dev = qc->dev;
unsigned int lba = tf->flags & ATA_TFLAG_LBA;
unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
u64 block = 0;
u32 n_block = 0;
u64 block;
u32 n_block;

tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf->protocol = qc->dev->xfer_protocol;
Expand All @@ -651,46 +722,26 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
}

/* Calculate the SCSI LBA and transfer length. */
if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
block |= ((u64)scsicmd[2]) << 24;
block |= ((u64)scsicmd[3]) << 16;
block |= ((u64)scsicmd[4]) << 8;
block |= ((u64)scsicmd[5]);

n_block |= ((u32)scsicmd[7]) << 8;
n_block |= ((u32)scsicmd[8]);

VPRINTK("ten-byte command\n");
} else if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
block |= ((u64)scsicmd[2]) << 8;
block |= ((u64)scsicmd[3]);

n_block |= ((u32)scsicmd[4]);
switch (scsicmd[0]) {
case READ_10:
case WRITE_10:
scsi_10_lba_len(scsicmd, &block, &n_block);
break;
case READ_6:
case WRITE_6:
scsi_6_lba_len(scsicmd, &block, &n_block);

/* for 6-byte r/w commands, transfer length 0
* means 256 blocks of data, not 0 block.
*/
if (!n_block)
n_block = 256;

VPRINTK("six-byte command\n");
} else if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
block |= ((u64)scsicmd[2]) << 56;
block |= ((u64)scsicmd[3]) << 48;
block |= ((u64)scsicmd[4]) << 40;
block |= ((u64)scsicmd[5]) << 32;
block |= ((u64)scsicmd[6]) << 24;
block |= ((u64)scsicmd[7]) << 16;
block |= ((u64)scsicmd[8]) << 8;
block |= ((u64)scsicmd[9]);

n_block |= ((u32)scsicmd[10]) << 24;
n_block |= ((u32)scsicmd[11]) << 16;
n_block |= ((u32)scsicmd[12]) << 8;
n_block |= ((u32)scsicmd[13]);

VPRINTK("sixteen-byte command\n");
} else {
break;
case READ_16:
case WRITE_16:
scsi_16_lba_len(scsicmd, &block, &n_block);
break;
default:
DPRINTK("no-byte command\n");
return 1;
}
Expand Down

0 comments on commit 3aef523

Please sign in to comment.