static void nv_adma_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 {
-       /* Since commands where a result TF is requested are not
-          executed in ADMA mode, the only time this function will be called
-          in ADMA mode will be if a command fails. In this case we
-          don't care about going into register mode with ADMA commands
-          pending, as the commands will all shortly be aborted anyway. */
+       /* Other than when internal or pass-through commands are executed,
+          the only time this function will be called in ADMA mode will be
+          if a command fails. In the failure case we don't care about going
+          into register mode with ADMA commands pending, as the commands will
+          all shortly be aborted anyway. We assume that NCQ commands are not
+          issued via passthrough, which is the only way that switching into
+          ADMA mode could abort outstanding commands. */
        nv_adma_register_mode(ap);
 
        ata_tf_read(ap, tf);
        struct nv_adma_port_priv *pp = qc->ap->private_data;
 
        /* ADMA engine can only be used for non-ATAPI DMA commands,
-          or interrupt-driven no-data commands, where a result taskfile
-          is not required. */
+          or interrupt-driven no-data commands. */
        if ((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
-          (qc->tf.flags & ATA_TFLAG_POLLING) ||
-          (qc->flags & ATA_QCFLAG_RESULT_TF))
+          (qc->tf.flags & ATA_TFLAG_POLLING))
                return 1;
 
        if ((qc->flags & ATA_QCFLAG_DMAMAP) ||
                       NV_CPB_CTL_IEN;
 
        if (nv_adma_use_reg_mode(qc)) {
+               BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
+                       (qc->flags & ATA_QCFLAG_DMAMAP));
                nv_adma_register_mode(qc->ap);
                ata_qc_prep(qc);
                return;
 
        VPRINTK("ENTER\n");
 
+       /* We can't handle result taskfile with NCQ commands, since
+          retrieving the taskfile switches us out of ADMA mode and would abort
+          existing commands. */
+       if (unlikely(qc->tf.protocol == ATA_PROT_NCQ &&
+                    (qc->flags & ATA_QCFLAG_RESULT_TF))) {
+               ata_dev_printk(qc->dev, KERN_ERR,
+                       "NCQ w/ RESULT_TF not allowed\n");
+               return AC_ERR_SYSTEM;
+       }
+
        if (nv_adma_use_reg_mode(qc)) {
                /* use ATA register mode */
                VPRINTK("using ATA register mode: 0x%lx\n", qc->flags);
+               BUG_ON(!(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) &&
+                       (qc->flags & ATA_QCFLAG_DMAMAP));
                nv_adma_register_mode(qc->ap);
                return ata_qc_issue_prot(qc);
        } else