aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-01-06 03:56:18 -0500
committerJens Axboe <axboe@suse.de>2006-01-06 03:56:18 -0500
commit9a3dccc42556537a48f39ee9a9e7ab90a933f766 (patch)
treee67d7b314d4e0732bfa5558bef4f1941ea80cb58
parent93c9338713d4e11102cd09b4670ad42a336b06a3 (diff)
[BLOCK] add FUA support to libata
Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jens Axboe <axboe@suse.de>
-rw-r--r--drivers/scsi/libata-core.c31
-rw-r--r--drivers/scsi/libata-scsi.c32
-rw-r--r--drivers/scsi/libata.h4
-rw-r--r--include/linux/ata.h6
-rw-r--r--include/linux/libata.h3
5 files changed, 61 insertions, 15 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 9ea102587914..bdfb0a88cd6f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -562,16 +562,28 @@ static const u8 ata_rw_cmds[] = {
562 ATA_CMD_WRITE_MULTI, 562 ATA_CMD_WRITE_MULTI,
563 ATA_CMD_READ_MULTI_EXT, 563 ATA_CMD_READ_MULTI_EXT,
564 ATA_CMD_WRITE_MULTI_EXT, 564 ATA_CMD_WRITE_MULTI_EXT,
565 0,
566 0,
567 0,
568 ATA_CMD_WRITE_MULTI_FUA_EXT,
565 /* pio */ 569 /* pio */
566 ATA_CMD_PIO_READ, 570 ATA_CMD_PIO_READ,
567 ATA_CMD_PIO_WRITE, 571 ATA_CMD_PIO_WRITE,
568 ATA_CMD_PIO_READ_EXT, 572 ATA_CMD_PIO_READ_EXT,
569 ATA_CMD_PIO_WRITE_EXT, 573 ATA_CMD_PIO_WRITE_EXT,
574 0,
575 0,
576 0,
577 0,
570 /* dma */ 578 /* dma */
571 ATA_CMD_READ, 579 ATA_CMD_READ,
572 ATA_CMD_WRITE, 580 ATA_CMD_WRITE,
573 ATA_CMD_READ_EXT, 581 ATA_CMD_READ_EXT,
574 ATA_CMD_WRITE_EXT 582 ATA_CMD_WRITE_EXT,
583 0,
584 0,
585 0,
586 ATA_CMD_WRITE_FUA_EXT
575}; 587};
576 588
577/** 589/**
@@ -584,25 +596,32 @@ static const u8 ata_rw_cmds[] = {
584 * LOCKING: 596 * LOCKING:
585 * caller. 597 * caller.
586 */ 598 */
587void ata_rwcmd_protocol(struct ata_queued_cmd *qc) 599int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
588{ 600{
589 struct ata_taskfile *tf = &qc->tf; 601 struct ata_taskfile *tf = &qc->tf;
590 struct ata_device *dev = qc->dev; 602 struct ata_device *dev = qc->dev;
603 u8 cmd;
591 604
592 int index, lba48, write; 605 int index, fua, lba48, write;
593 606
607 fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0;
594 lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0; 608 lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
595 write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0; 609 write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
596 610
597 if (dev->flags & ATA_DFLAG_PIO) { 611 if (dev->flags & ATA_DFLAG_PIO) {
598 tf->protocol = ATA_PROT_PIO; 612 tf->protocol = ATA_PROT_PIO;
599 index = dev->multi_count ? 0 : 4; 613 index = dev->multi_count ? 0 : 8;
600 } else { 614 } else {
601 tf->protocol = ATA_PROT_DMA; 615 tf->protocol = ATA_PROT_DMA;
602 index = 8; 616 index = 16;
603 } 617 }
604 618
605 tf->command = ata_rw_cmds[index + lba48 + write]; 619 cmd = ata_rw_cmds[index + fua + lba48 + write];
620 if (cmd) {
621 tf->command = cmd;
622 return 0;
623 }
624 return -1;
606} 625}
607 626
608static const char * const xfer_mode_str[] = { 627static const char * const xfer_mode_str[] = {
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)
1695unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf, 1701unsigned 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
2472void ata_scsi_simulate(u16 *id, 2490void 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
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index 251e53bdc6e0..e03ce48b7b4b 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -32,6 +32,8 @@
32#define DRV_VERSION "1.20" /* must be exactly four chars */ 32#define DRV_VERSION "1.20" /* must be exactly four chars */
33 33
34struct ata_scsi_args { 34struct ata_scsi_args {
35 struct ata_port *ap;
36 struct ata_device *dev;
35 u16 *id; 37 u16 *id;
36 struct scsi_cmnd *cmd; 38 struct scsi_cmnd *cmd;
37 void (*done)(struct scsi_cmnd *); 39 void (*done)(struct scsi_cmnd *);
@@ -41,7 +43,7 @@ struct ata_scsi_args {
41extern int atapi_enabled; 43extern int atapi_enabled;
42extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, 44extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
43 struct ata_device *dev); 45 struct ata_device *dev);
44extern void ata_rwcmd_protocol(struct ata_queued_cmd *qc); 46extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
45extern void ata_qc_free(struct ata_queued_cmd *qc); 47extern void ata_qc_free(struct ata_queued_cmd *qc);
46extern int ata_qc_issue(struct ata_queued_cmd *qc); 48extern int ata_qc_issue(struct ata_queued_cmd *qc);
47extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); 49extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
diff --git a/include/linux/ata.h b/include/linux/ata.h
index d2873b732bb1..f63dad4165b1 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -129,6 +129,7 @@ enum {
129 ATA_CMD_READ_EXT = 0x25, 129 ATA_CMD_READ_EXT = 0x25,
130 ATA_CMD_WRITE = 0xCA, 130 ATA_CMD_WRITE = 0xCA,
131 ATA_CMD_WRITE_EXT = 0x35, 131 ATA_CMD_WRITE_EXT = 0x35,
132 ATA_CMD_WRITE_FUA_EXT = 0x3D,
132 ATA_CMD_PIO_READ = 0x20, 133 ATA_CMD_PIO_READ = 0x20,
133 ATA_CMD_PIO_READ_EXT = 0x24, 134 ATA_CMD_PIO_READ_EXT = 0x24,
134 ATA_CMD_PIO_WRITE = 0x30, 135 ATA_CMD_PIO_WRITE = 0x30,
@@ -137,6 +138,7 @@ enum {
137 ATA_CMD_READ_MULTI_EXT = 0x29, 138 ATA_CMD_READ_MULTI_EXT = 0x29,
138 ATA_CMD_WRITE_MULTI = 0xC5, 139 ATA_CMD_WRITE_MULTI = 0xC5,
139 ATA_CMD_WRITE_MULTI_EXT = 0x39, 140 ATA_CMD_WRITE_MULTI_EXT = 0x39,
141 ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE,
140 ATA_CMD_SET_FEATURES = 0xEF, 142 ATA_CMD_SET_FEATURES = 0xEF,
141 ATA_CMD_PACKET = 0xA0, 143 ATA_CMD_PACKET = 0xA0,
142 ATA_CMD_VERIFY = 0x40, 144 ATA_CMD_VERIFY = 0x40,
@@ -192,6 +194,7 @@ enum {
192 ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */ 194 ATA_TFLAG_DEVICE = (1 << 2), /* enable r/w to device reg */
193 ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */ 195 ATA_TFLAG_WRITE = (1 << 3), /* data dir: host->dev==1 (write) */
194 ATA_TFLAG_LBA = (1 << 4), /* enable LBA */ 196 ATA_TFLAG_LBA = (1 << 4), /* enable LBA */
197 ATA_TFLAG_FUA = (1 << 5), /* enable FUA */
195}; 198};
196 199
197enum ata_tf_protocols { 200enum ata_tf_protocols {
@@ -245,7 +248,8 @@ struct ata_taskfile {
245#define ata_id_is_sata(id) ((id)[93] == 0) 248#define ata_id_is_sata(id) ((id)[93] == 0)
246#define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6)) 249#define ata_id_rahead_enabled(id) ((id)[85] & (1 << 6))
247#define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5)) 250#define ata_id_wcache_enabled(id) ((id)[85] & (1 << 5))
248#define ata_id_has_flush(id) ((id)[83] & (1 << 12)) 251#define ata_id_has_fua(id) ((id)[84] & (1 << 6))
252#define ata_id_has_flush(id) ((id)[83] & (1 << 12))
249#define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13)) 253#define ata_id_has_flush_ext(id) ((id)[83] & (1 << 13))
250#define ata_id_has_lba48(id) ((id)[83] & (1 << 10)) 254#define ata_id_has_lba48(id) ((id)[83] & (1 << 10))
251#define ata_id_has_wcache(id) ((id)[82] & (1 << 5)) 255#define ata_id_has_wcache(id) ((id)[82] & (1 << 5))
diff --git a/include/linux/libata.h b/include/linux/libata.h
index e828e172ccbf..6db2c0845731 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -480,7 +480,8 @@ extern u8 ata_bmdma_status(struct ata_port *ap);
480extern void ata_bmdma_irq_clear(struct ata_port *ap); 480extern void ata_bmdma_irq_clear(struct ata_port *ap);
481extern void ata_qc_complete(struct ata_queued_cmd *qc); 481extern void ata_qc_complete(struct ata_queued_cmd *qc);
482extern void ata_eng_timeout(struct ata_port *ap); 482extern void ata_eng_timeout(struct ata_port *ap);
483extern void ata_scsi_simulate(u16 *id, struct scsi_cmnd *cmd, 483extern void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
484 struct scsi_cmnd *cmd,
484 void (*done)(struct scsi_cmnd *)); 485 void (*done)(struct scsi_cmnd *));
485extern int ata_std_bios_param(struct scsi_device *sdev, 486extern int ata_std_bios_param(struct scsi_device *sdev,
486 struct block_device *bdev, 487 struct block_device *bdev,