diff options
author | Tejun Heo <htejun@gmail.com> | 2006-11-14 22:37:35 +0900 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-01 22:46:00 -0500 |
commit | 35b649fe2587b2e569c17c022ba3506ba441b6a2 (patch) | |
tree | 07d1b36f0241d48fa71159e7bc7a096ac5842bed /drivers/ata/libata-core.c | |
parent | 750426aa1ad1ddd1fa8bb4ed531a7956f3b9a27c (diff) |
[PATCH] libata: implement ata_tf_read_block()
Implement ata_tf_read_block().
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r-- | drivers/ata/libata-core.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 13dcef809e5..3fd7c793270 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -240,6 +240,49 @@ int ata_rwcmd_protocol(struct ata_queued_cmd *qc) } /** + * ata_tf_read_block - Read block address from ATA taskfile + * @tf: ATA taskfile of interest + * @dev: ATA device @tf belongs to + * + * LOCKING: + * None. + * + * Read block address from @tf. This function can handle all + * three address formats - LBA, LBA48 and CHS. tf->protocol and + * flags select the address format to use. + * + * RETURNS: + * Block address read from @tf. + */ +u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev) +{ + u64 block = 0; + + if (tf->flags & ATA_TFLAG_LBA) { + if (tf->flags & ATA_TFLAG_LBA48) { + block |= (u64)tf->hob_lbah << 40; + block |= (u64)tf->hob_lbam << 32; + block |= tf->hob_lbal << 24; + } else + block |= (tf->device & 0xf) << 24; + + block |= tf->lbah << 16; + block |= tf->lbam << 8; + block |= tf->lbal; + } else { + u32 cyl, head, sect; + + cyl = tf->lbam | (tf->lbah << 8); + head = tf->device & 0xf; + sect = tf->lbal; + + block = (cyl * dev->heads + head) * dev->sectors + sect; + } + + return block; +} + +/** * ata_pack_xfermask - Pack pio, mwdma and udma masks into xfer_mask * @pio_mask: pio_mask * @mwdma_mask: mwdma_mask |