aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlbert Lee <albertcc@tw.ibm.com>2005-11-01 06:33:20 -0500
committerJeff Garzik <jgarzik@pobox.com>2005-11-09 01:22:19 -0500
commit07f6f7d074e68d56d82e7cc5c65096033ac8dc56 (patch)
treed420722be7721691e5c56dc5a0ff326e926a58e6
parentfbcdd80b0d5bde06f3483b9a13f9599a0452431c (diff)
[PATCH] libata irq-pio: add read/write multiple support
- add is_multi_taskfile() to ata.h - initialize ata_device->multi_count with device identify data - use ata_pio_sectors() to support r/w multiple commands Signed-off-by: Albert Lee <albertcc@tw.ibm.com> ======== Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
-rw-r--r--drivers/scsi/libata-core.c44
-rw-r--r--include/linux/ata.h8
2 files changed, 46 insertions, 6 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 2e0e6cca327c..59a4a26bc13f 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -1261,6 +1261,12 @@ retry:
1261 1261
1262 } 1262 }
1263 1263
1264 if (dev->id[59] & 0x100) {
1265 dev->multi_count = dev->id[59] & 0xff;
1266 DPRINTK("ata%u: dev %u multi count %u\n",
1267 ap->id, device, dev->multi_count);
1268 }
1269
1264 ap->host->max_cmd_len = 16; 1270 ap->host->max_cmd_len = 16;
1265 } 1271 }
1266 1272
@@ -2804,7 +2810,7 @@ static int ata_pio_complete (struct ata_port *ap)
2804 * we enter, BSY will be cleared in a chk-status or two. If not, 2810 * we enter, BSY will be cleared in a chk-status or two. If not,
2805 * the drive is probably seeking or something. Snooze for a couple 2811 * the drive is probably seeking or something. Snooze for a couple
2806 * msecs, then chk-status again. If still busy, fall back to 2812 * msecs, then chk-status again. If still busy, fall back to
2807 * HSM_ST_POLL state. 2813 * HSM_ST_LAST_POLL state.
2808 */ 2814 */
2809 drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10); 2815 drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
2810 if (drv_stat & (ATA_BUSY | ATA_DRQ)) { 2816 if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
@@ -3021,6 +3027,32 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
3021} 3027}
3022 3028
3023/** 3029/**
3030 * ata_pio_sectors - Transfer one or many 512-byte sectors.
3031 * @qc: Command on going
3032 *
3033 * Transfer one or many ATA_SECT_SIZE of data from/to the
3034 * ATA device for the DRQ request.
3035 *
3036 * LOCKING:
3037 * Inherited from caller.
3038 */
3039
3040static void ata_pio_sectors(struct ata_queued_cmd *qc)
3041{
3042 if (is_multi_taskfile(&qc->tf)) {
3043 /* READ/WRITE MULTIPLE */
3044 unsigned int nsect;
3045
3046 assert(qc->dev->multi_count);
3047
3048 nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
3049 while (nsect--)
3050 ata_pio_sector(qc);
3051 } else
3052 ata_pio_sector(qc);
3053}
3054
3055/**
3024 * atapi_send_cdb - Write CDB bytes to hardware 3056 * atapi_send_cdb - Write CDB bytes to hardware
3025 * @ap: Port to which ATAPI device is attached. 3057 * @ap: Port to which ATAPI device is attached.
3026 * @qc: Taskfile currently active 3058 * @qc: Taskfile currently active
@@ -3118,11 +3150,11 @@ static int ata_pio_first_block(struct ata_port *ap)
3118 * send first data block. 3150 * send first data block.
3119 */ 3151 */
3120 3152
3121 /* ata_pio_sector() might change the state to HSM_ST_LAST. 3153 /* ata_pio_sectors() might change the state to HSM_ST_LAST.
3122 * so, the state is changed here before ata_pio_sector(). 3154 * so, the state is changed here before ata_pio_sectors().
3123 */ 3155 */
3124 ap->hsm_task_state = HSM_ST; 3156 ap->hsm_task_state = HSM_ST;
3125 ata_pio_sector(qc); 3157 ata_pio_sectors(qc);
3126 ata_altstatus(ap); /* flush */ 3158 ata_altstatus(ap); /* flush */
3127 } else 3159 } else
3128 /* send CDB */ 3160 /* send CDB */
@@ -3327,7 +3359,7 @@ static void ata_pio_block(struct ata_port *ap)
3327 return; 3359 return;
3328 } 3360 }
3329 3361
3330 ata_pio_sector(qc); 3362 ata_pio_sectors(qc);
3331 } 3363 }
3332 3364
3333 ata_altstatus(ap); /* flush */ 3365 ata_altstatus(ap); /* flush */
@@ -4213,7 +4245,7 @@ fsm_start:
4213 goto fsm_start; 4245 goto fsm_start;
4214 } 4246 }
4215 4247
4216 ata_pio_sector(qc); 4248 ata_pio_sectors(qc);
4217 4249
4218 if (ap->hsm_task_state == HSM_ST_LAST && 4250 if (ap->hsm_task_state == HSM_ST_LAST &&
4219 (!(qc->tf.flags & ATA_TFLAG_WRITE))) { 4251 (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
diff --git a/include/linux/ata.h b/include/linux/ata.h
index d54da3306d2c..f512104a1a3f 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -293,6 +293,14 @@ static inline int is_atapi_taskfile(const struct ata_taskfile *tf)
293 (tf->protocol == ATA_PROT_ATAPI_DMA); 293 (tf->protocol == ATA_PROT_ATAPI_DMA);
294} 294}
295 295
296static inline int is_multi_taskfile(struct ata_taskfile *tf)
297{
298 return (tf->command == ATA_CMD_READ_MULTI) ||
299 (tf->command == ATA_CMD_WRITE_MULTI) ||
300 (tf->command == ATA_CMD_READ_MULTI_EXT) ||
301 (tf->command == ATA_CMD_WRITE_MULTI_EXT);
302}
303
296static inline int ata_ok(u8 status) 304static inline int ata_ok(u8 status)
297{ 305{
298 return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR)) 306 return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))