From e2cec77117a6e4fcbac2601e2f7b0b3f4f5a4c84 Mon Sep 17 00:00:00 2001 From: Albert Lee Date: Sat, 25 Mar 2006 17:43:49 +0800 Subject: [PATCH] [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 Signed-off-by: Jeff Garzik --- drivers/scsi/libata-core.c | 206 +++++++++++++++++++------------------ 1 file changed, 106 insertions(+), 100 deletions(-) diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 0eb75e2dc0e2..7214530ac161 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -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: