[libata scsi] add ata_scsi_set_sense helper
[linux-block.git] / drivers / scsi / libata-scsi.c
index f8ddc2a29e9a744cd32b50a059da6e7430730734..bca9a5016b1746e79aec8018d47c7505b4241d7b 100644 (file)
@@ -225,7 +225,7 @@ void ata_to_sense_error(struct ata_queued_cmd *qc, u8 drv_stat)
        };
        int i = 0;
 
-       cmd->result = SAM_STAT_CHECK_CONDITION;
+       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
        /*
         *      Is this an error we can process/parse
@@ -435,10 +435,21 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc,
                return 1;       /* power conditions not supported */
        if (scsicmd[4] & 0x1) {
                tf->nsect = 1;  /* 1 sector, lba=0 */
-               tf->lbah = 0x0;
-               tf->lbam = 0x0;
-               tf->lbal = 0x0;
-               tf->device |= ATA_LBA;
+
+               if (qc->dev->flags & ATA_DFLAG_LBA) {
+                       qc->tf.flags |= ATA_TFLAG_LBA;
+
+                       tf->lbah = 0x0;
+                       tf->lbam = 0x0;
+                       tf->lbal = 0x0;
+                       tf->device |= ATA_LBA;
+               } else {
+                       /* CHS */
+                       tf->lbal = 0x1; /* sect */
+                       tf->lbam = 0x0; /* cyl low */
+                       tf->lbah = 0x0; /* cyl high */
+               }
+
                tf->command = ATA_CMD_VERIFY;   /* READ VERIFY */
        } else {
                tf->nsect = 0;  /* time period value (0 implies now) */
@@ -487,6 +498,99 @@ static unsigned int ata_scsi_flush_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
        return 0;
 }
 
+/**
+ *     scsi_6_lba_len - Get LBA and transfer length
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Calculate LBA and transfer length for 6-byte commands.
+ *
+ *     RETURNS:
+ *     @plba: the LBA
+ *     @plen: the transfer length
+ */
+
+static void scsi_6_lba_len(u8 *scsicmd, u64 *plba, u32 *plen)
+{
+       u64 lba = 0;
+       u32 len = 0;
+
+       VPRINTK("six-byte command\n");
+
+       lba |= ((u64)scsicmd[2]) << 8;
+       lba |= ((u64)scsicmd[3]);
+
+       len |= ((u32)scsicmd[4]);
+
+       *plba = lba;
+       *plen = len;
+}
+
+/**
+ *     scsi_10_lba_len - Get LBA and transfer length
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Calculate LBA and transfer length for 10-byte commands.
+ *
+ *     RETURNS:
+ *     @plba: the LBA
+ *     @plen: the transfer length
+ */
+
+static void scsi_10_lba_len(u8 *scsicmd, u64 *plba, u32 *plen)
+{
+       u64 lba = 0;
+       u32 len = 0;
+
+       VPRINTK("ten-byte command\n");
+
+       lba |= ((u64)scsicmd[2]) << 24;
+       lba |= ((u64)scsicmd[3]) << 16;
+       lba |= ((u64)scsicmd[4]) << 8;
+       lba |= ((u64)scsicmd[5]);
+
+       len |= ((u32)scsicmd[7]) << 8;
+       len |= ((u32)scsicmd[8]);
+
+       *plba = lba;
+       *plen = len;
+}
+
+/**
+ *     scsi_16_lba_len - Get LBA and transfer length
+ *     @scsicmd: SCSI command to translate
+ *
+ *     Calculate LBA and transfer length for 16-byte commands.
+ *
+ *     RETURNS:
+ *     @plba: the LBA
+ *     @plen: the transfer length
+ */
+
+static void scsi_16_lba_len(u8 *scsicmd, u64 *plba, u32 *plen)
+{
+       u64 lba = 0;
+       u32 len = 0;
+
+       VPRINTK("sixteen-byte command\n");
+
+       lba |= ((u64)scsicmd[2]) << 56;
+       lba |= ((u64)scsicmd[3]) << 48;
+       lba |= ((u64)scsicmd[4]) << 40;
+       lba |= ((u64)scsicmd[5]) << 32;
+       lba |= ((u64)scsicmd[6]) << 24;
+       lba |= ((u64)scsicmd[7]) << 16;
+       lba |= ((u64)scsicmd[8]) << 8;
+       lba |= ((u64)scsicmd[9]);
+
+       len |= ((u32)scsicmd[10]) << 24;
+       len |= ((u32)scsicmd[11]) << 16;
+       len |= ((u32)scsicmd[12]) << 8;
+       len |= ((u32)scsicmd[13]);
+
+       *plba = lba;
+       *plen = len;
+}
+
 /**
  *     ata_scsi_verify_xlat - Translate SCSI VERIFY command into an ATA one
  *     @qc: Storage for translated ATA taskfile
@@ -508,38 +612,16 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
        unsigned int lba   = tf->flags & ATA_TFLAG_LBA;
        unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
        u64 dev_sectors = qc->dev->n_sectors;
-       u64 block = 0;
-       u32 n_block = 0;
+       u64 block;
+       u32 n_block;
 
        tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
        tf->protocol = ATA_PROT_NODATA;
 
-       if (scsicmd[0] == VERIFY) {
-               block |= ((u64)scsicmd[2]) << 24;
-               block |= ((u64)scsicmd[3]) << 16;
-               block |= ((u64)scsicmd[4]) << 8;
-               block |= ((u64)scsicmd[5]);
-
-               n_block |= ((u32)scsicmd[7]) << 8;
-               n_block |= ((u32)scsicmd[8]);
-       }
-
-       else if (scsicmd[0] == VERIFY_16) {
-               block |= ((u64)scsicmd[2]) << 56;
-               block |= ((u64)scsicmd[3]) << 48;
-               block |= ((u64)scsicmd[4]) << 40;
-               block |= ((u64)scsicmd[5]) << 32;
-               block |= ((u64)scsicmd[6]) << 24;
-               block |= ((u64)scsicmd[7]) << 16;
-               block |= ((u64)scsicmd[8]) << 8;
-               block |= ((u64)scsicmd[9]);
-
-               n_block |= ((u32)scsicmd[10]) << 24;
-               n_block |= ((u32)scsicmd[11]) << 16;
-               n_block |= ((u32)scsicmd[12]) << 8;
-               n_block |= ((u32)scsicmd[13]);
-       }
-
+       if (scsicmd[0] == VERIFY)
+               scsi_10_lba_len(scsicmd, &block, &n_block);
+       else if (scsicmd[0] == VERIFY_16)
+               scsi_16_lba_len(scsicmd, &block, &n_block);
        else
                return 1;
 
@@ -589,7 +671,8 @@ static unsigned int ata_scsi_verify_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
                head  = track % dev->heads;
                sect  = (u32)block % dev->sectors + 1;
 
-               DPRINTK("block[%u] track[%u] cyl[%u] head[%u] sect[%u] \n", (u32)block, track, cyl, head, sect);
+               DPRINTK("block %u track %u cyl %u head %u sect %u\n",
+                       (u32)block, track, cyl, head, sect);
                
                /* Check whether the converted CHS can fit. 
                   Cylinder: 0-65535 
@@ -635,8 +718,8 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
        struct ata_device *dev = qc->dev;
        unsigned int lba   = tf->flags & ATA_TFLAG_LBA;
        unsigned int lba48 = tf->flags & ATA_TFLAG_LBA48;
-       u64 block = 0;
-       u32 n_block = 0;
+       u64 block;
+       u32 n_block;
 
        tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
        tf->protocol = qc->dev->xfer_protocol;
@@ -650,49 +733,37 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
        }
 
        /* Calculate the SCSI LBA and transfer length. */
-       if (scsicmd[0] == READ_10 || scsicmd[0] == WRITE_10) {
-               block |= ((u64)scsicmd[2]) << 24;
-               block |= ((u64)scsicmd[3]) << 16;
-               block |= ((u64)scsicmd[4]) << 8;
-               block |= ((u64)scsicmd[5]);
-
-               n_block |= ((u32)scsicmd[7]) << 8;
-               n_block |= ((u32)scsicmd[8]);
-
-               VPRINTK("ten-byte command\n");
-       } else if (scsicmd[0] == READ_6 || scsicmd[0] == WRITE_6) {
-               block |= ((u64)scsicmd[2]) << 8;
-               block |= ((u64)scsicmd[3]);
+       switch (scsicmd[0]) {
+       case READ_10:
+       case WRITE_10:
+               scsi_10_lba_len(scsicmd, &block, &n_block);
+               break;
+       case READ_6:
+       case WRITE_6:
+               scsi_6_lba_len(scsicmd, &block, &n_block);
 
-               n_block |= ((u32)scsicmd[4]);
+               /* for 6-byte r/w commands, transfer length 0
+                * means 256 blocks of data, not 0 block.
+                */
                if (!n_block)
                        n_block = 256;
-       
-               VPRINTK("six-byte command\n");
-       } else if (scsicmd[0] == READ_16 || scsicmd[0] == WRITE_16) {
-               block |= ((u64)scsicmd[2]) << 56;
-               block |= ((u64)scsicmd[3]) << 48;
-               block |= ((u64)scsicmd[4]) << 40;
-               block |= ((u64)scsicmd[5]) << 32;
-               block |= ((u64)scsicmd[6]) << 24;
-               block |= ((u64)scsicmd[7]) << 16;
-               block |= ((u64)scsicmd[8]) << 8;
-               block |= ((u64)scsicmd[9]);
-
-               n_block |= ((u32)scsicmd[10]) << 24;
-               n_block |= ((u32)scsicmd[11]) << 16;
-               n_block |= ((u32)scsicmd[12]) << 8;
-               n_block |= ((u32)scsicmd[13]);
-
-               VPRINTK("sixteen-byte command\n");
-       } else {
+               break;
+       case READ_16:
+       case WRITE_16:
+               scsi_16_lba_len(scsicmd, &block, &n_block);
+               break;
+       default:
                DPRINTK("no-byte command\n");
                return 1;
        }
 
        /* Check and compose ATA command */
        if (!n_block)
-               /* In ATA, sector count 0 means 256 or 65536 sectors, not 0 sectors. */
+               /* For 10-byte and 16-byte SCSI R/W commands, transfer
+                * length 0 means transfer 0 block of data.
+                * However, for ATA R/W commands, sector count 0 means
+                * 256 or 65536 sectors, not 0 sectors as in SCSI.
+                */
                return 1;
 
        if (lba) {
@@ -715,7 +786,7 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
 
                        tf->device |= (block >> 24) & 0xf;
                }
-       
+
                qc->nsect = n_block;
                tf->nsect = n_block & 0xff;
 
@@ -731,23 +802,23 @@ static unsigned int ata_scsi_rw_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
                /* The request -may- be too large for CHS addressing. */
                if ((block >> 28) || (n_block > 256))
                        return 1;
-                       
+
                /* Convert LBA to CHS */
                track = (u32)block / dev->sectors;
                cyl   = track / dev->heads;
                head  = track % dev->heads;
                sect  = (u32)block % dev->sectors + 1;
 
-               DPRINTK("block[%u] track[%u] cyl[%u] head[%u] sect[%u] \n", 
+               DPRINTK("block %u track %u cyl %u head %u sect %u\n",
                        (u32)block, track, cyl, head, sect);
-               
+
                /* Check whether the converted CHS can fit. 
                   Cylinder: 0-65535 
                   Head: 0-15
                   Sector: 1-255*/
-               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect)) 
+               if ((cyl >> 16) || (head >> 4) || (sect >> 8) || (!sect))
                        return 1;
-               
+
                qc->nsect = n_block;
                tf->nsect = n_block & 0xff; /* Sector count 0 means 256 sectors */
                tf->lbal = sect;
@@ -1379,6 +1450,34 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
        return 0;
 }
 
+/**
+ *     ata_scsi_set_sense - Set SCSI sense data and status
+ *     @cmd: SCSI request to be handled
+ *     @sk: SCSI-defined sense key
+ *     @asc: SCSI-defined additional sense code
+ *     @ascq: SCSI-defined additional sense code qualifier
+ *
+ *     Helper function that builds a valid fixed format, current
+ *     response code and the given sense key (sk), additional sense
+ *     code (asc) and additional sense code qualifier (ascq) with
+ *     a SCSI command status of %SAM_STAT_CHECK_CONDITION and
+ *     DRIVER_SENSE set in the upper bits of scsi_cmnd::result .
+ *
+ *     LOCKING:
+ *     Not required
+ */
+
+void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+{
+       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+
+       cmd->sense_buffer[0] = 0x70;    /* fixed format, current */
+       cmd->sense_buffer[2] = sk;
+       cmd->sense_buffer[7] = 18 - 8;  /* additional sense length */
+       cmd->sense_buffer[12] = asc;
+       cmd->sense_buffer[13] = ascq;
+}
+
 /**
  *     ata_scsi_badcmd - End a SCSI request with an error
  *     @cmd: SCSI request to be handled
@@ -1397,7 +1496,7 @@ unsigned int ata_scsiop_report_luns(struct ata_scsi_args *args, u8 *rbuf,
 void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8 asc, u8 ascq)
 {
        DPRINTK("ENTER\n");
-       cmd->result = SAM_STAT_CHECK_CONDITION;
+       cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
        cmd->sense_buffer[0] = 0x70;
        cmd->sense_buffer[2] = ILLEGAL_REQUEST;
@@ -1408,19 +1507,79 @@ void ata_scsi_badcmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), u8
        done(cmd);
 }
 
+void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
+                        struct scsi_cmnd *cmd)
+{
+       DECLARE_COMPLETION(wait);
+       struct ata_queued_cmd *qc;
+       unsigned long flags;
+       int rc;
+
+       DPRINTK("ATAPI request sense\n");
+
+       qc = ata_qc_new_init(ap, dev);
+       BUG_ON(qc == NULL);
+
+       /* FIXME: is this needed? */
+       memset(cmd->sense_buffer, 0, sizeof(cmd->sense_buffer));
+
+       ata_sg_init_one(qc, cmd->sense_buffer, sizeof(cmd->sense_buffer));
+       qc->dma_dir = DMA_FROM_DEVICE;
+
+       memset(&qc->cdb, 0, ap->cdb_len);
+       qc->cdb[0] = REQUEST_SENSE;
+       qc->cdb[4] = SCSI_SENSE_BUFFERSIZE;
+
+       qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       qc->tf.command = ATA_CMD_PACKET;
+
+       qc->tf.protocol = ATA_PROT_ATAPI;
+       qc->tf.lbam = (8 * 1024) & 0xff;
+       qc->tf.lbah = (8 * 1024) >> 8;
+       qc->nbytes = SCSI_SENSE_BUFFERSIZE;
+
+       qc->waiting = &wait;
+       qc->complete_fn = ata_qc_complete_noop;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       rc = ata_qc_issue(qc);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       if (rc)
+               ata_port_disable(ap);
+       else
+               wait_for_completion(&wait);
+
+       DPRINTK("EXIT\n");
+}
+
 static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 {
        struct scsi_cmnd *cmd = qc->scsicmd;
 
-       if (unlikely(drv_stat & (ATA_ERR | ATA_BUSY | ATA_DRQ))) {
+       VPRINTK("ENTER, drv_stat == 0x%x\n", drv_stat);
+
+       if (unlikely(drv_stat & (ATA_BUSY | ATA_DRQ)))
+               ata_to_sense_error(qc, drv_stat);
+
+       else if (unlikely(drv_stat & ATA_ERR)) {
                DPRINTK("request check condition\n");
 
+               /* FIXME: command completion with check condition
+                * but no sense causes the error handler to run,
+                * which then issues REQUEST SENSE, fills in the sense 
+                * buffer, and completes the command (for the second
+                * time).  We need to issue REQUEST SENSE some other
+                * way, to avoid completing the command twice.
+                */
                cmd->result = SAM_STAT_CHECK_CONDITION;
 
                qc->scsidone(cmd);
 
                return 1;
-       } else {
+       }
+
+       else {
                u8 *scsicmd = cmd->cmnd;
 
                if (scsicmd[0] == INQUIRY) {
@@ -1428,15 +1587,30 @@ static int atapi_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
                        unsigned int buflen;
 
                        buflen = ata_scsi_rbuf_get(cmd, &buf);
-                       buf[2] = 0x5;
-                       buf[3] = (buf[3] & 0xf0) | 2;
+
+       /* ATAPI devices typically report zero for their SCSI version,
+        * and sometimes deviate from the spec WRT response data
+        * format.  If SCSI version is reported as zero like normal,
+        * then we make the following fixups:  1) Fake MMC-5 version,
+        * to indicate to the Linux scsi midlayer this is a modern
+        * device.  2) Ensure response data format / ATAPI information
+        * are always correct.
+        */
+       /* FIXME: do we ever override EVPD pages and the like, with
+        * this code?
+        */
+                       if (buf[2] == 0) {
+                               buf[2] = 0x5;
+                               buf[3] = 0x32;
+                       }
+
                        ata_scsi_rbuf_put(cmd, buf);
                }
+
                cmd->result = SAM_STAT_GOOD;
        }
 
        qc->scsidone(cmd);
-
        return 0;
 }
 /**
@@ -1537,10 +1711,10 @@ ata_scsi_find_dev(struct ata_port *ap, struct scsi_device *scsidev)
        if (unlikely(!ata_dev_present(dev)))
                return NULL;
 
-#ifndef ATA_ENABLE_ATAPI
-       if (unlikely(dev->class == ATA_DEV_ATAPI))
-               return NULL;
-#endif
+       if (!atapi_enabled) {
+               if (unlikely(dev->class == ATA_DEV_ATAPI))
+                       return NULL;
+       }
 
        return dev;
 }
@@ -1745,3 +1919,19 @@ void ata_scsi_simulate(u16 *id,
        }
 }
 
+void ata_scsi_scan_host(struct ata_port *ap)
+{
+       struct ata_device *dev;
+       unsigned int i;
+
+       if (ap->flags & ATA_FLAG_PORT_DISABLED)
+               return;
+
+       for (i = 0; i < ATA_MAX_DEVICES; i++) {
+               dev = &ap->device[i];
+
+               if (ata_dev_present(dev))
+                       scsi_scan_target(&ap->host->shost_gendev, 0, i, 0, 0);
+       }
+}
+