diff options
author | Tejun Heo <htejun@gmail.com> | 2006-01-06 03:56:18 -0500 |
---|---|---|
committer | Jens Axboe <axboe@suse.de> | 2006-01-06 03:56:18 -0500 |
commit | 9a3dccc42556537a48f39ee9a9e7ab90a933f766 (patch) | |
tree | e67d7b314d4e0732bfa5558bef4f1941ea80cb58 /drivers/scsi/libata-scsi.c | |
parent | 93c9338713d4e11102cd09b4670ad42a336b06a3 (diff) |
[BLOCK] add FUA support to libata
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'drivers/scsi/libata-scsi.c')
-rw-r--r-- | drivers/scsi/libata-scsi.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index e0439be4b573..2c644cbb6e9c 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -1080,11 +1080,13 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
1080 | scsicmd[0] == WRITE_16) | 1080 | scsicmd[0] == WRITE_16) |
1081 | tf->flags |= ATA_TFLAG_WRITE; | 1081 | tf->flags |= ATA_TFLAG_WRITE; |
1082 | 1082 | ||
1083 | /* Calculate the SCSI LBA and transfer length. */ | 1083 | /* Calculate the SCSI LBA, transfer length and FUA. */ |
1084 | switch (scsicmd[0]) { | 1084 | switch (scsicmd[0]) { |
1085 | case READ_10: | 1085 | case READ_10: |
1086 | case WRITE_10: | 1086 | case WRITE_10: |
1087 | scsi_10_lba_len(scsicmd, &block, &n_block); | 1087 | scsi_10_lba_len(scsicmd, &block, &n_block); |
1088 | if (unlikely(scsicmd[1] & (1 << 3))) | ||
1089 | tf->flags |= ATA_TFLAG_FUA; | ||
1088 | break; | 1090 | break; |
1089 | case READ_6: | 1091 | case READ_6: |
1090 | case WRITE_6: | 1092 | case WRITE_6: |
@@ -1099,6 +1101,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
1099 | case READ_16: | 1101 | case READ_16: |
1100 | case WRITE_16: | 1102 | case WRITE_16: |
1101 | scsi_16_lba_len(scsicmd, &block, &n_block); | 1103 | scsi_16_lba_len(scsicmd, &block, &n_block); |
1104 | if (unlikely(scsicmd[1] & (1 << 3))) | ||
1105 | tf->flags |= ATA_TFLAG_FUA; | ||
1102 | break; | 1106 | break; |
1103 | default: | 1107 | default: |
1104 | DPRINTK("no-byte command\n"); | 1108 | DPRINTK("no-byte command\n"); |
@@ -1142,7 +1146,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
1142 | tf->device |= (block >> 24) & 0xf; | 1146 | tf->device |= (block >> 24) & 0xf; |
1143 | } | 1147 | } |
1144 | 1148 | ||
1145 | ata_rwcmd_protocol(qc); | 1149 | if (unlikely(ata_rwcmd_protocol(qc) < 0)) |
1150 | goto invalid_fld; | ||
1146 | 1151 | ||
1147 | qc->nsect = n_block; | 1152 | qc->nsect = n_block; |
1148 | tf->nsect = n_block & 0xff; | 1153 | tf->nsect = n_block & 0xff; |
@@ -1160,7 +1165,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, const u8 *scsicm | |||
1160 | if ((block >> 28) || (n_block > 256)) | 1165 | if ((block >> 28) || (n_block > 256)) |
1161 | goto out_of_range; | 1166 | goto out_of_range; |
1162 | 1167 | ||
1163 | ata_rwcmd_protocol(qc); | 1168 | if (unlikely(ata_rwcmd_protocol(qc) < 0)) |
1169 | goto invalid_fld; | ||
1164 | 1170 | ||
1165 | /* Convert LBA to CHS */ | 1171 | /* Convert LBA to CHS */ |
1166 | track = (u32)block / dev->sectors; | 1172 | track = (u32)block / dev->sectors; |
@@ -1695,6 +1701,7 @@ static unsigned int ata_msense_rw_recovery(u8 **ptr_io, const u8 *last) | |||
1695 | unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | 1701 | unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, |
1696 | unsigned int buflen) | 1702 | unsigned int buflen) |
1697 | { | 1703 | { |
1704 | struct ata_device *dev = args->dev; | ||
1698 | u8 *scsicmd = args->cmd->cmnd, *p, *last; | 1705 | u8 *scsicmd = args->cmd->cmnd, *p, *last; |
1699 | const u8 sat_blk_desc[] = { | 1706 | const u8 sat_blk_desc[] = { |
1700 | 0, 0, 0, 0, /* number of blocks: sat unspecified */ | 1707 | 0, 0, 0, 0, /* number of blocks: sat unspecified */ |
@@ -1703,6 +1710,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | |||
1703 | }; | 1710 | }; |
1704 | u8 pg, spg; | 1711 | u8 pg, spg; |
1705 | unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen; | 1712 | unsigned int ebd, page_control, six_byte, output_len, alloc_len, minlen; |
1713 | u8 dpofua; | ||
1706 | 1714 | ||
1707 | VPRINTK("ENTER\n"); | 1715 | VPRINTK("ENTER\n"); |
1708 | 1716 | ||
@@ -1771,9 +1779,17 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | |||
1771 | 1779 | ||
1772 | if (minlen < 1) | 1780 | if (minlen < 1) |
1773 | return 0; | 1781 | return 0; |
1782 | |||
1783 | dpofua = 0; | ||
1784 | if (ata_id_has_fua(args->id) && dev->flags & ATA_DFLAG_LBA48 && | ||
1785 | (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) | ||
1786 | dpofua = 1 << 4; | ||
1787 | |||
1774 | if (six_byte) { | 1788 | if (six_byte) { |
1775 | output_len--; | 1789 | output_len--; |
1776 | rbuf[0] = output_len; | 1790 | rbuf[0] = output_len; |
1791 | if (minlen > 2) | ||
1792 | rbuf[2] |= dpofua; | ||
1777 | if (ebd) { | 1793 | if (ebd) { |
1778 | if (minlen > 3) | 1794 | if (minlen > 3) |
1779 | rbuf[3] = sizeof(sat_blk_desc); | 1795 | rbuf[3] = sizeof(sat_blk_desc); |
@@ -1786,6 +1802,8 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, | |||
1786 | rbuf[0] = output_len >> 8; | 1802 | rbuf[0] = output_len >> 8; |
1787 | if (minlen > 1) | 1803 | if (minlen > 1) |
1788 | rbuf[1] = output_len; | 1804 | rbuf[1] = output_len; |
1805 | if (minlen > 3) | ||
1806 | rbuf[3] |= dpofua; | ||
1789 | if (ebd) { | 1807 | if (ebd) { |
1790 | if (minlen > 7) | 1808 | if (minlen > 7) |
1791 | rbuf[7] = sizeof(sat_blk_desc); | 1809 | rbuf[7] = sizeof(sat_blk_desc); |
@@ -2446,7 +2464,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | |||
2446 | if (xlat_func) | 2464 | if (xlat_func) |
2447 | ata_scsi_translate(ap, dev, cmd, done, xlat_func); | 2465 | ata_scsi_translate(ap, dev, cmd, done, xlat_func); |
2448 | else | 2466 | else |
2449 | ata_scsi_simulate(dev->id, cmd, done); | 2467 | ata_scsi_simulate(ap, dev, cmd, done); |
2450 | } else | 2468 | } else |
2451 | ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); | 2469 | ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); |
2452 | 2470 | ||
@@ -2469,14 +2487,16 @@ out_unlock: | |||
2469 | * spin_lock_irqsave(host_set lock) | 2487 | * spin_lock_irqsave(host_set lock) |
2470 | */ | 2488 | */ |
2471 | 2489 | ||
2472 | void ata_scsi_simulate(u16 *id, | 2490 | void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev, |
2473 | struct scsi_cmnd *cmd, | 2491 | struct scsi_cmnd *cmd, |
2474 | void (*done)(struct scsi_cmnd *)) | 2492 | void (*done)(struct scsi_cmnd *)) |
2475 | { | 2493 | { |
2476 | struct ata_scsi_args args; | 2494 | struct ata_scsi_args args; |
2477 | const u8 *scsicmd = cmd->cmnd; | 2495 | const u8 *scsicmd = cmd->cmnd; |
2478 | 2496 | ||
2479 | args.id = id; | 2497 | args.ap = ap; |
2498 | args.dev = dev; | ||
2499 | args.id = dev->id; | ||
2480 | args.cmd = cmd; | 2500 | args.cmd = cmd; |
2481 | args.done = done; | 2501 | args.done = done; |
2482 | 2502 | ||