]> git.hungrycats.org Git - linux/commitdiff
[libata] handle non-data ATAPI commands via interrupt
authorJeff Garzik <jgarzik@redhat.com>
Sat, 15 May 2004 14:07:32 +0000 (10:07 -0400)
committerJeff Garzik <jgarzik@redhat.com>
Sat, 15 May 2004 14:07:32 +0000 (10:07 -0400)
It's easier to do it this way, than polling, at the moment.

Also, fix a test in ata_scsi_translate that was incorrectly
erroring-out non-data commands.

drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c

index 14dee1c4361ef68995a0ad566aae18ee7bd2bdc7..9c4117cb6a6e73cc6b3a27debe5d458ba87155b7 100644 (file)
@@ -2677,6 +2677,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
                handled = 1;
                break;
 
+       case ATA_PROT_ATAPI:
        case ATA_PROT_NODATA:   /* command completion, but no data xfer */
                status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
                DPRINTK("BUS_NODATA (drv_stat 0x%X)\n", status);
@@ -2837,9 +2838,16 @@ static void atapi_packet_task(void *_data)
              qc->scsicmd->cmnd, ap->host->max_cmd_len / 4);
 
        /* if we are DMA'ing, irq handler takes over from here */
-       if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) {
+       if (qc->tf.protocol == ATA_PROT_ATAPI_DMA)
                ap->ops->bmdma_start(qc);           /* initiate bmdma */
-       } else {
+
+       /* non-data commands are also handled via irq */
+       else if (qc->scsicmd->sc_data_direction == SCSI_DATA_NONE) {
+               /* do nothing */
+       }
+
+       /* PIO commands are handled by polling */
+       else {
                ap->pio_task_state = PIO_ST;
                queue_work(ata_wq, &ap->pio_task);
        }
index 8456f458c2f81694615be47f966cbd39a4f7b1cf..ab308576b2e69b3e6d1ecb4006c84844619521be 100644 (file)
@@ -46,8 +46,8 @@ static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
  *     @geom: location to which geometry will be output
  *
  *     Generic bios head/sector/cylinder calculator
- *     used by sd. Most BIOSes nowadays expect a XXX/255/16  (CHS) 
- *     mapping. Some situations may arise where the disk is not 
+ *     used by sd. Most BIOSes nowadays expect a XXX/255/16  (CHS)
+ *     mapping. Some situations may arise where the disk is not
  *     bootable if this is not used.
  *
  *     LOCKING:
@@ -57,7 +57,7 @@ static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
  *     Zero.
  */
 int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
-                      sector_t capacity, int geom[]) 
+                      sector_t capacity, int geom[])
 {
        geom[0] = 255;
        geom[1] = 63;
@@ -362,19 +362,20 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
 
        VPRINTK("ENTER\n");
 
-       if (unlikely(cmd->request_bufflen < 1)) {
-               printk(KERN_WARNING "ata%u(%u): empty request buffer\n",
-                      ap->id, dev->devno);
-               goto err_out;
-       }
-
        qc = ata_scsi_qc_new(ap, dev, cmd, done);
        if (!qc)
                return;
 
        if (cmd->sc_data_direction == SCSI_DATA_READ ||
-           cmd->sc_data_direction == SCSI_DATA_WRITE)
+           cmd->sc_data_direction == SCSI_DATA_WRITE) {
+               if (unlikely(cmd->request_bufflen < 1)) {
+                       printk(KERN_WARNING "ata%u(%u): WARNING: zero len r/w req\n",
+                              ap->id, dev->devno);
+                       goto err_out;
+               }
+
                qc->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */
+       }
 
        if (xlat_func(qc, scsicmd))
                goto err_out;
@@ -910,12 +911,18 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 
        qc->tf.command = ATA_CMD_PACKET;
 
-       if ((cmd->sc_data_direction == SCSI_DATA_NONE) ||
-           ((qc->flags & ATA_QCFLAG_DMA) == 0)) {
+       /* no data - interrupt-driven */
+       if (cmd->sc_data_direction == SCSI_DATA_NONE)
+               qc->tf.protocol = ATA_PROT_ATAPI;
+
+       /* PIO data xfer - polling */
+       else if ((qc->flags & ATA_QCFLAG_DMA) == 0) {
                ata_qc_set_polling(qc);
                qc->tf.protocol = ATA_PROT_ATAPI;
                qc->tf.lbam = (8 * 1024) & 0xff;
                qc->tf.lbah = (8 * 1024) >> 8;
+
+       /* DMA data xfer - interrupt-driven */
        } else {
                qc->flags |= ATA_QCFLAG_SG; /* data is present; dma-map it */
                qc->tf.protocol = ATA_PROT_ATAPI_DMA;