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;
/* 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: