提交 07f6f7d0 编写于 作者: A Albert Lee 提交者: Jeff Garzik

[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: NAlbert Lee <albertcc@tw.ibm.com>

========
Signed-off-by: NJeff Garzik <jgarzik@pobox.com>
上级 fbcdd80b
...@@ -1261,6 +1261,12 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) ...@@ -1261,6 +1261,12 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
} }
if (dev->id[59] & 0x100) {
dev->multi_count = dev->id[59] & 0xff;
DPRINTK("ata%u: dev %u multi count %u\n",
ap->id, device, dev->multi_count);
}
ap->host->max_cmd_len = 16; ap->host->max_cmd_len = 16;
} }
...@@ -2804,7 +2810,7 @@ static int ata_pio_complete (struct ata_port *ap) ...@@ -2804,7 +2810,7 @@ static int ata_pio_complete (struct ata_port *ap)
* we enter, BSY will be cleared in a chk-status or two. If not, * we enter, BSY will be cleared in a chk-status or two. If not,
* the drive is probably seeking or something. Snooze for a couple * the drive is probably seeking or something. Snooze for a couple
* msecs, then chk-status again. If still busy, fall back to * msecs, then chk-status again. If still busy, fall back to
* HSM_ST_POLL state. * HSM_ST_LAST_POLL state.
*/ */
drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10); drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
if (drv_stat & (ATA_BUSY | ATA_DRQ)) { if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
...@@ -3020,6 +3026,32 @@ static void ata_pio_sector(struct ata_queued_cmd *qc) ...@@ -3020,6 +3026,32 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
} }
} }
/**
* ata_pio_sectors - Transfer one or many 512-byte sectors.
* @qc: Command on going
*
* Transfer one or many ATA_SECT_SIZE of data from/to the
* ATA device for the DRQ request.
*
* LOCKING:
* Inherited from caller.
*/
static void ata_pio_sectors(struct ata_queued_cmd *qc)
{
if (is_multi_taskfile(&qc->tf)) {
/* READ/WRITE MULTIPLE */
unsigned int nsect;
assert(qc->dev->multi_count);
nsect = min(qc->nsect - qc->cursect, qc->dev->multi_count);
while (nsect--)
ata_pio_sector(qc);
} else
ata_pio_sector(qc);
}
/** /**
* atapi_send_cdb - Write CDB bytes to hardware * atapi_send_cdb - Write CDB bytes to hardware
* @ap: Port to which ATAPI device is attached. * @ap: Port to which ATAPI device is attached.
...@@ -3118,11 +3150,11 @@ static int ata_pio_first_block(struct ata_port *ap) ...@@ -3118,11 +3150,11 @@ static int ata_pio_first_block(struct ata_port *ap)
* send first data block. * send first data block.
*/ */
/* ata_pio_sector() might change the state to HSM_ST_LAST. /* ata_pio_sectors() might change the state to HSM_ST_LAST.
* so, the state is changed here before ata_pio_sector(). * so, the state is changed here before ata_pio_sectors().
*/ */
ap->hsm_task_state = HSM_ST; ap->hsm_task_state = HSM_ST;
ata_pio_sector(qc); ata_pio_sectors(qc);
ata_altstatus(ap); /* flush */ ata_altstatus(ap); /* flush */
} else } else
/* send CDB */ /* send CDB */
...@@ -3327,7 +3359,7 @@ static void ata_pio_block(struct ata_port *ap) ...@@ -3327,7 +3359,7 @@ static void ata_pio_block(struct ata_port *ap)
return; return;
} }
ata_pio_sector(qc); ata_pio_sectors(qc);
} }
ata_altstatus(ap); /* flush */ ata_altstatus(ap); /* flush */
...@@ -4213,7 +4245,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -4213,7 +4245,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
goto fsm_start; goto fsm_start;
} }
ata_pio_sector(qc); ata_pio_sectors(qc);
if (ap->hsm_task_state == HSM_ST_LAST && if (ap->hsm_task_state == HSM_ST_LAST &&
(!(qc->tf.flags & ATA_TFLAG_WRITE))) { (!(qc->tf.flags & ATA_TFLAG_WRITE))) {
......
...@@ -293,6 +293,14 @@ static inline int is_atapi_taskfile(const struct ata_taskfile *tf) ...@@ -293,6 +293,14 @@ static inline int is_atapi_taskfile(const struct ata_taskfile *tf)
(tf->protocol == ATA_PROT_ATAPI_DMA); (tf->protocol == ATA_PROT_ATAPI_DMA);
} }
static inline int is_multi_taskfile(struct ata_taskfile *tf)
{
return (tf->command == ATA_CMD_READ_MULTI) ||
(tf->command == ATA_CMD_WRITE_MULTI) ||
(tf->command == ATA_CMD_READ_MULTI_EXT) ||
(tf->command == ATA_CMD_WRITE_MULTI_EXT);
}
static inline int ata_ok(u8 status) static inline int ata_ok(u8 status)
{ {
return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR)) return ((status & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ | ATA_ERR))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册