]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ata/libata-scsi.c
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzi...
[linux-2.6-omap-h63xx.git] / drivers / ata / libata-scsi.c
index 499ccc628d81f3f80326ecd1340cd1fea4463e79..f3b4b15a8dc49509802a7cf06bae5fba2d8f6dfb 100644 (file)
@@ -190,6 +190,85 @@ static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
        scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
 }
 
+static ssize_t
+ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr,
+                         const char *buf, size_t count)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct ata_port *ap = ata_shost_to_port(shost);
+       if (ap->ops->em_store && (ap->flags & ATA_FLAG_EM))
+               return ap->ops->em_store(ap, buf, count);
+       return -EINVAL;
+}
+
+static ssize_t
+ata_scsi_em_message_show(struct device *dev, struct device_attribute *attr,
+                        char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct ata_port *ap = ata_shost_to_port(shost);
+
+       if (ap->ops->em_show && (ap->flags & ATA_FLAG_EM))
+               return ap->ops->em_show(ap, buf);
+       return -EINVAL;
+}
+DEVICE_ATTR(em_message, S_IRUGO | S_IWUGO,
+               ata_scsi_em_message_show, ata_scsi_em_message_store);
+EXPORT_SYMBOL_GPL(dev_attr_em_message);
+
+static ssize_t
+ata_scsi_em_message_type_show(struct device *dev, struct device_attribute *attr,
+                             char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct ata_port *ap = ata_shost_to_port(shost);
+
+       return snprintf(buf, 23, "%d\n", ap->em_message_type);
+}
+DEVICE_ATTR(em_message_type, S_IRUGO,
+                 ata_scsi_em_message_type_show, NULL);
+EXPORT_SYMBOL_GPL(dev_attr_em_message_type);
+
+static ssize_t
+ata_scsi_activity_show(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
+       struct ata_device *atadev = ata_scsi_find_dev(ap, sdev);
+
+       if (ap->ops->sw_activity_show && (ap->flags & ATA_FLAG_SW_ACTIVITY))
+               return ap->ops->sw_activity_show(atadev, buf);
+       return -EINVAL;
+}
+
+static ssize_t
+ata_scsi_activity_store(struct device *dev, struct device_attribute *attr,
+       const char *buf, size_t count)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct ata_port *ap = ata_shost_to_port(sdev->host);
+       struct ata_device *atadev = ata_scsi_find_dev(ap, sdev);
+       enum sw_activity val;
+       int rc;
+
+       if (ap->ops->sw_activity_store && (ap->flags & ATA_FLAG_SW_ACTIVITY)) {
+               val = simple_strtoul(buf, NULL, 0);
+               switch (val) {
+               case OFF: case BLINK_ON: case BLINK_OFF:
+                       rc = ap->ops->sw_activity_store(atadev, val);
+                       if (!rc)
+                               return count;
+                       else
+                               return rc;
+               }
+       }
+       return -EINVAL;
+}
+DEVICE_ATTR(sw_activity, S_IWUGO | S_IRUGO, ata_scsi_activity_show,
+                       ata_scsi_activity_store);
+EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
+
 static void ata_scsi_invalid_field(struct scsi_cmnd *cmd,
                                   void (*done)(struct scsi_cmnd *))
 {
@@ -1779,7 +1858,9 @@ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf)
        const u8 pages[] = {
                0x00,   /* page 0x00, this page */
                0x80,   /* page 0x80, unit serial no page */
-               0x83    /* page 0x83, device ident page */
+               0x83,   /* page 0x83, device ident page */
+               0x89,   /* page 0x89, ata info page */
+               0xb1,   /* page 0xb1, block device characteristics page */
        };
 
        rbuf[3] = sizeof(pages);        /* number of supported VPD pages */
@@ -1900,6 +1981,19 @@ static unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf)
        return 0;
 }
 
+static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf)
+{
+       rbuf[1] = 0xb1;
+       rbuf[3] = 0x3c;
+       if (ata_id_major_version(args->id) > 7) {
+               rbuf[4] = args->id[217] >> 8;
+               rbuf[5] = args->id[217];
+               rbuf[7] = args->id[168] & 0xf;
+       }
+
+       return 0;
+}
+
 /**
  *     ata_scsiop_noop - Command handler that simply returns success.
  *     @args: device IDENTIFY data / SCSI command of interest.
@@ -2921,6 +3015,9 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
                case 0x89:
                        ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89);
                        break;
+               case 0xb1:
+                       ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b1);
+                       break;
                default:
                        ata_scsi_invalid_field(cmd, done);
                        break;