[PATCH] libata-dev: Move out the HSM code from ata_host_intr()

Move out the irq-pio HSM code from ata_host_intr() to the new ata_hsm_move() function verbatim.

Signed-off-by: Albert Lee <albertcc@tw.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
This commit is contained in:
Albert Lee 2006-03-25 17:43:49 +08:00 committed by Jeff Garzik
parent 19d5d7309a
commit e2cec77117
1 changed files with 106 additions and 100 deletions

View File

@ -3805,6 +3805,111 @@ static void ata_pio_error(struct ata_port *ap)
ata_poll_qc_complete(qc);
}
static void ata_hsm_move(struct ata_port *ap, struct ata_queued_cmd *qc,
u8 status)
{
/* check error */
if (unlikely(status & (ATA_ERR | ATA_DF))) {
qc->err_mask |= AC_ERR_DEV;
ap->hsm_task_state = HSM_ST_ERR;
}
fsm_start:
switch (ap->hsm_task_state) {
case HSM_ST_FIRST:
/* Some pre-ATAPI-4 devices assert INTRQ
* at this state when ready to receive CDB.
*/
/* check device status */
if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) {
/* Wrong status. Let EH handle this */
qc->err_mask |= AC_ERR_HSM;
ap->hsm_task_state = HSM_ST_ERR;
goto fsm_start;
}
atapi_send_cdb(ap, qc);
break;
case HSM_ST:
/* complete command or read/write the data register */
if (qc->tf.protocol == ATA_PROT_ATAPI) {
/* ATAPI PIO protocol */
if ((status & ATA_DRQ) == 0) {
/* no more data to transfer */
ap->hsm_task_state = HSM_ST_LAST;
goto fsm_start;
}
atapi_pio_bytes(qc);
if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
/* bad ireason reported by device */
goto fsm_start;
} else {
/* ATA PIO protocol */
if (unlikely((status & ATA_DRQ) == 0)) {
/* handle BSY=0, DRQ=0 as error */
qc->err_mask |= AC_ERR_HSM;
ap->hsm_task_state = HSM_ST_ERR;
goto fsm_start;
}
ata_pio_sectors(qc);
if (ap->hsm_task_state == HSM_ST_LAST &&
(!(qc->tf.flags & ATA_TFLAG_WRITE))) {
/* all data read */
ata_altstatus(ap);
status = ata_chk_status(ap);
goto fsm_start;
}
}
ata_altstatus(ap); /* flush */
break;
case HSM_ST_LAST:
if (unlikely(status & ATA_DRQ)) {
/* handle DRQ=1 as error */
qc->err_mask |= AC_ERR_HSM;
ap->hsm_task_state = HSM_ST_ERR;
goto fsm_start;
}
/* no more data to transfer */
DPRINTK("ata%u: command complete, drv_stat 0x%x\n",
ap->id, status);
ap->hsm_task_state = HSM_ST_IDLE;
/* complete taskfile transaction */
qc->err_mask |= ac_err_mask(status);
ata_qc_complete(qc);
break;
case HSM_ST_ERR:
if (qc->tf.command != ATA_CMD_PACKET)
printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n",
ap->id, status, host_stat);
/* make sure qc->err_mask is available to
* know what's wrong and recover
*/
WARN_ON(qc->err_mask == 0);
ap->hsm_task_state = HSM_ST_IDLE;
ata_qc_complete(qc);
break;
default:
goto idle_irq;
}
}
static void ata_pio_task(void *_data)
{
struct ata_port *ap = _data;
@ -4316,106 +4421,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
/* ack bmdma irq events */
ap->ops->irq_clear(ap);
/* check error */
if (unlikely(status & (ATA_ERR | ATA_DF))) {
qc->err_mask |= AC_ERR_DEV;
ap->hsm_task_state = HSM_ST_ERR;
}
fsm_start:
switch (ap->hsm_task_state) {
case HSM_ST_FIRST:
/* Some pre-ATAPI-4 devices assert INTRQ
* at this state when ready to receive CDB.
*/
/* check device status */
if (unlikely((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)) {
/* Wrong status. Let EH handle this */
qc->err_mask |= AC_ERR_HSM;
ap->hsm_task_state = HSM_ST_ERR;
goto fsm_start;
}
atapi_send_cdb(ap, qc);
break;
case HSM_ST:
/* complete command or read/write the data register */
if (qc->tf.protocol == ATA_PROT_ATAPI) {
/* ATAPI PIO protocol */
if ((status & ATA_DRQ) == 0) {
/* no more data to transfer */
ap->hsm_task_state = HSM_ST_LAST;
goto fsm_start;
}
atapi_pio_bytes(qc);
if (unlikely(ap->hsm_task_state == HSM_ST_ERR))
/* bad ireason reported by device */
goto fsm_start;
} else {
/* ATA PIO protocol */
if (unlikely((status & ATA_DRQ) == 0)) {
/* handle BSY=0, DRQ=0 as error */
qc->err_mask |= AC_ERR_HSM;
ap->hsm_task_state = HSM_ST_ERR;
goto fsm_start;
}
ata_pio_sectors(qc);
if (ap->hsm_task_state == HSM_ST_LAST &&
(!(qc->tf.flags & ATA_TFLAG_WRITE))) {
/* all data read */
ata_altstatus(ap);
status = ata_chk_status(ap);
goto fsm_start;
}
}
ata_altstatus(ap); /* flush */
break;
case HSM_ST_LAST:
if (unlikely(status & ATA_DRQ)) {
/* handle DRQ=1 as error */
qc->err_mask |= AC_ERR_HSM;
ap->hsm_task_state = HSM_ST_ERR;
goto fsm_start;
}
/* no more data to transfer */
DPRINTK("ata%u: command complete, drv_stat 0x%x\n",
ap->id, status);
ap->hsm_task_state = HSM_ST_IDLE;
/* complete taskfile transaction */
qc->err_mask |= ac_err_mask(status);
ata_qc_complete(qc);
break;
case HSM_ST_ERR:
if (qc->tf.command != ATA_CMD_PACKET)
printk(KERN_ERR "ata%u: command error, drv_stat 0x%x host_stat 0x%x\n",
ap->id, status, host_stat);
/* make sure qc->err_mask is available to
* know what's wrong and recover
*/
WARN_ON(qc->err_mask == 0);
ap->hsm_task_state = HSM_ST_IDLE;
ata_qc_complete(qc);
break;
default:
goto idle_irq;
}
ata_hsm_move(ap, qc, status);
return 1; /* irq handled */
idle_irq: