aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Lord <liml@rtr.ca>2007-03-16 10:22:26 -0400
committerJeff Garzik <jeff@garzik.org>2007-04-28 14:16:01 -0400
commit5a5dbd18a7496ed403f6f54bb20c955c65482fa5 (patch)
tree031eec40ab42ac4ab04e59db539b8126ac31fb6d
parent1234010684bb9cde51125ec3d1c71054a9f24f47 (diff)
libata: add support for READ/WRITE LONG
The READ/WRITE LONG commands are theoretically obsolete, but the majority of drives in existance still implement them. The WRITE_LONG and WRITE_LONG_ONCE commands are of particular interest for fault injection testing -- eg. creating "media errors" at specific locations on a disk. The fussy bit is that these commands require a non-standard sector size, usually 520 bytes instead of 512. This patch adds support to libata for READ/WRITE LONG commands issued via SG_IO/ATA_16. Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/libata-core.c20
-rw-r--r--drivers/ata/libata-scsi.c12
-rw-r--r--include/linux/ata.h6
-rw-r--r--include/linux/libata.h2
4 files changed, 30 insertions, 10 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 971a737a8734..96bf86f67388 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4106,10 +4106,10 @@ void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
4106 4106
4107 4107
4108/** 4108/**
4109 * ata_pio_sector - Transfer ATA_SECT_SIZE (512 bytes) of data. 4109 * ata_pio_sector - Transfer a sector of data.
4110 * @qc: Command on going 4110 * @qc: Command on going
4111 * 4111 *
4112 * Transfer ATA_SECT_SIZE of data from/to the ATA device. 4112 * Transfer qc->sect_size bytes of data from/to the ATA device.
4113 * 4113 *
4114 * LOCKING: 4114 * LOCKING:
4115 * Inherited from caller. 4115 * Inherited from caller.
@@ -4124,7 +4124,7 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
4124 unsigned int offset; 4124 unsigned int offset;
4125 unsigned char *buf; 4125 unsigned char *buf;
4126 4126
4127 if (qc->curbytes == qc->nbytes - ATA_SECT_SIZE) 4127 if (qc->curbytes == qc->nbytes - qc->sect_size)
4128 ap->hsm_task_state = HSM_ST_LAST; 4128 ap->hsm_task_state = HSM_ST_LAST;
4129 4129
4130 page = sg[qc->cursg].page; 4130 page = sg[qc->cursg].page;
@@ -4144,17 +4144,17 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
4144 buf = kmap_atomic(page, KM_IRQ0); 4144 buf = kmap_atomic(page, KM_IRQ0);
4145 4145
4146 /* do the actual data transfer */ 4146 /* do the actual data transfer */
4147 ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write); 4147 ap->ops->data_xfer(qc->dev, buf + offset, qc->sect_size, do_write);
4148 4148
4149 kunmap_atomic(buf, KM_IRQ0); 4149 kunmap_atomic(buf, KM_IRQ0);
4150 local_irq_restore(flags); 4150 local_irq_restore(flags);
4151 } else { 4151 } else {
4152 buf = page_address(page); 4152 buf = page_address(page);
4153 ap->ops->data_xfer(qc->dev, buf + offset, ATA_SECT_SIZE, do_write); 4153 ap->ops->data_xfer(qc->dev, buf + offset, qc->sect_size, do_write);
4154 } 4154 }
4155 4155
4156 qc->curbytes += ATA_SECT_SIZE; 4156 qc->curbytes += qc->sect_size;
4157 qc->cursg_ofs += ATA_SECT_SIZE; 4157 qc->cursg_ofs += qc->sect_size;
4158 4158
4159 if (qc->cursg_ofs == (&sg[qc->cursg])->length) { 4159 if (qc->cursg_ofs == (&sg[qc->cursg])->length) {
4160 qc->cursg++; 4160 qc->cursg++;
@@ -4163,10 +4163,10 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
4163} 4163}
4164 4164
4165/** 4165/**
4166 * ata_pio_sectors - Transfer one or many 512-byte sectors. 4166 * ata_pio_sectors - Transfer one or many sectors.
4167 * @qc: Command on going 4167 * @qc: Command on going
4168 * 4168 *
4169 * Transfer one or many ATA_SECT_SIZE of data from/to the 4169 * Transfer one or many sectors of data from/to the
4170 * ATA device for the DRQ request. 4170 * ATA device for the DRQ request.
4171 * 4171 *
4172 * LOCKING: 4172 * LOCKING:
@@ -4181,7 +4181,7 @@ static void ata_pio_sectors(struct ata_queued_cmd *qc)
4181 4181
4182 WARN_ON(qc->dev->multi_count == 0); 4182 WARN_ON(qc->dev->multi_count == 0);
4183 4183
4184 nsect = min((qc->nbytes - qc->curbytes) / ATA_SECT_SIZE, 4184 nsect = min((qc->nbytes - qc->curbytes) / qc->sect_size,
4185 qc->dev->multi_count); 4185 qc->dev->multi_count);
4186 while (nsect--) 4186 while (nsect--)
4187 ata_pio_sector(qc); 4187 ata_pio_sector(qc);
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 7d41afe8ccbc..563ef0bfb038 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2678,6 +2678,18 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
2678 tf->device = qc->dev->devno ? 2678 tf->device = qc->dev->devno ?
2679 tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1; 2679 tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
2680 2680
2681 /* READ/WRITE LONG use a non-standard sect_size */
2682 qc->sect_size = ATA_SECT_SIZE;
2683 switch (tf->command) {
2684 case ATA_CMD_READ_LONG:
2685 case ATA_CMD_READ_LONG_ONCE:
2686 case ATA_CMD_WRITE_LONG:
2687 case ATA_CMD_WRITE_LONG_ONCE:
2688 if (tf->protocol != ATA_PROT_PIO || tf->nsect != 1)
2689 goto invalid_fld;
2690 qc->sect_size = scmd->request_bufflen;
2691 }
2692
2681 /* 2693 /*
2682 * Filter SET_FEATURES - XFER MODE command -- otherwise, 2694 * Filter SET_FEATURES - XFER MODE command -- otherwise,
2683 * SET_FEATURES - XFER MODE must be preceded/succeeded 2695 * SET_FEATURES - XFER MODE must be preceded/succeeded
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 6caeb98e29dd..ffb6cdc5010d 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -164,6 +164,12 @@ enum {
164 /* READ_LOG_EXT pages */ 164 /* READ_LOG_EXT pages */
165 ATA_LOG_SATA_NCQ = 0x10, 165 ATA_LOG_SATA_NCQ = 0x10,
166 166
167 /* READ/WRITE LONG (obsolete) */
168 ATA_CMD_READ_LONG = 0x22,
169 ATA_CMD_READ_LONG_ONCE = 0x23,
170 ATA_CMD_WRITE_LONG = 0x32,
171 ATA_CMD_WRITE_LONG_ONCE = 0x33,
172
167 /* SETFEATURES stuff */ 173 /* SETFEATURES stuff */
168 SETFEATURES_XFER = 0x03, 174 SETFEATURES_XFER = 0x03,
169 XFER_UDMA_7 = 0x47, 175 XFER_UDMA_7 = 0x47,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 5a40a8d95114..12237d4b9f9b 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -427,6 +427,7 @@ struct ata_queued_cmd {
427 int dma_dir; 427 int dma_dir;
428 428
429 unsigned int pad_len; 429 unsigned int pad_len;
430 unsigned int sect_size;
430 431
431 unsigned int nbytes; 432 unsigned int nbytes;
432 unsigned int curbytes; 433 unsigned int curbytes;
@@ -1182,6 +1183,7 @@ static inline void ata_qc_reinit(struct ata_queued_cmd *qc)
1182 qc->n_elem = 0; 1183 qc->n_elem = 0;
1183 qc->err_mask = 0; 1184 qc->err_mask = 0;
1184 qc->pad_len = 0; 1185 qc->pad_len = 0;
1186 qc->sect_size = ATA_SECT_SIZE;
1185 1187
1186 ata_tf_init(qc->dev, &qc->tf); 1188 ata_tf_init(qc->dev, &qc->tf);
1187 1189