diff options
Diffstat (limited to 'drivers/ata/libata-scsi.c')
| -rw-r--r-- | drivers/ata/libata-scsi.c | 99 |
1 files changed, 98 insertions, 1 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 499ccc628d81..f3b4b15a8dc4 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
| @@ -190,6 +190,85 @@ static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq) | |||
| 190 | scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq); | 190 | scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq); |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | static ssize_t | ||
| 194 | ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr, | ||
| 195 | const char *buf, size_t count) | ||
| 196 | { | ||
| 197 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 198 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 199 | if (ap->ops->em_store && (ap->flags & ATA_FLAG_EM)) | ||
| 200 | return ap->ops->em_store(ap, buf, count); | ||
| 201 | return -EINVAL; | ||
| 202 | } | ||
| 203 | |||
| 204 | static ssize_t | ||
| 205 | ata_scsi_em_message_show(struct device *dev, struct device_attribute *attr, | ||
| 206 | char *buf) | ||
| 207 | { | ||
| 208 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 209 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 210 | |||
| 211 | if (ap->ops->em_show && (ap->flags & ATA_FLAG_EM)) | ||
| 212 | return ap->ops->em_show(ap, buf); | ||
| 213 | return -EINVAL; | ||
| 214 | } | ||
| 215 | DEVICE_ATTR(em_message, S_IRUGO | S_IWUGO, | ||
| 216 | ata_scsi_em_message_show, ata_scsi_em_message_store); | ||
| 217 | EXPORT_SYMBOL_GPL(dev_attr_em_message); | ||
| 218 | |||
| 219 | static ssize_t | ||
| 220 | ata_scsi_em_message_type_show(struct device *dev, struct device_attribute *attr, | ||
| 221 | char *buf) | ||
| 222 | { | ||
| 223 | struct Scsi_Host *shost = class_to_shost(dev); | ||
| 224 | struct ata_port *ap = ata_shost_to_port(shost); | ||
| 225 | |||
| 226 | return snprintf(buf, 23, "%d\n", ap->em_message_type); | ||
| 227 | } | ||
| 228 | DEVICE_ATTR(em_message_type, S_IRUGO, | ||
| 229 | ata_scsi_em_message_type_show, NULL); | ||
| 230 | EXPORT_SYMBOL_GPL(dev_attr_em_message_type); | ||
| 231 | |||
| 232 | static ssize_t | ||
| 233 | ata_scsi_activity_show(struct device *dev, struct device_attribute *attr, | ||
| 234 | char *buf) | ||
| 235 | { | ||
| 236 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 237 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
| 238 | struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); | ||
| 239 | |||
| 240 | if (ap->ops->sw_activity_show && (ap->flags & ATA_FLAG_SW_ACTIVITY)) | ||
| 241 | return ap->ops->sw_activity_show(atadev, buf); | ||
| 242 | return -EINVAL; | ||
| 243 | } | ||
| 244 | |||
| 245 | static ssize_t | ||
| 246 | ata_scsi_activity_store(struct device *dev, struct device_attribute *attr, | ||
| 247 | const char *buf, size_t count) | ||
| 248 | { | ||
| 249 | struct scsi_device *sdev = to_scsi_device(dev); | ||
| 250 | struct ata_port *ap = ata_shost_to_port(sdev->host); | ||
| 251 | struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); | ||
| 252 | enum sw_activity val; | ||
| 253 | int rc; | ||
| 254 | |||
| 255 | if (ap->ops->sw_activity_store && (ap->flags & ATA_FLAG_SW_ACTIVITY)) { | ||
| 256 | val = simple_strtoul(buf, NULL, 0); | ||
| 257 | switch (val) { | ||
| 258 | case OFF: case BLINK_ON: case BLINK_OFF: | ||
| 259 | rc = ap->ops->sw_activity_store(atadev, val); | ||
| 260 | if (!rc) | ||
| 261 | return count; | ||
| 262 | else | ||
| 263 | return rc; | ||
| 264 | } | ||
| 265 | } | ||
| 266 | return -EINVAL; | ||
| 267 | } | ||
| 268 | DEVICE_ATTR(sw_activity, S_IWUGO | S_IRUGO, ata_scsi_activity_show, | ||
| 269 | ata_scsi_activity_store); | ||
| 270 | EXPORT_SYMBOL_GPL(dev_attr_sw_activity); | ||
| 271 | |||
| 193 | static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, | 272 | static void ata_scsi_invalid_field(struct scsi_cmnd *cmd, |
| 194 | void (*done)(struct scsi_cmnd *)) | 273 | void (*done)(struct scsi_cmnd *)) |
| 195 | { | 274 | { |
| @@ -1779,7 +1858,9 @@ static unsigned int ata_scsiop_inq_00(struct ata_scsi_args *args, u8 *rbuf) | |||
| 1779 | const u8 pages[] = { | 1858 | const u8 pages[] = { |
| 1780 | 0x00, /* page 0x00, this page */ | 1859 | 0x00, /* page 0x00, this page */ |
| 1781 | 0x80, /* page 0x80, unit serial no page */ | 1860 | 0x80, /* page 0x80, unit serial no page */ |
| 1782 | 0x83 /* page 0x83, device ident page */ | 1861 | 0x83, /* page 0x83, device ident page */ |
| 1862 | 0x89, /* page 0x89, ata info page */ | ||
| 1863 | 0xb1, /* page 0xb1, block device characteristics page */ | ||
| 1783 | }; | 1864 | }; |
| 1784 | 1865 | ||
| 1785 | rbuf[3] = sizeof(pages); /* number of supported VPD pages */ | 1866 | 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) | |||
| 1900 | return 0; | 1981 | return 0; |
| 1901 | } | 1982 | } |
| 1902 | 1983 | ||
| 1984 | static unsigned int ata_scsiop_inq_b1(struct ata_scsi_args *args, u8 *rbuf) | ||
| 1985 | { | ||
| 1986 | rbuf[1] = 0xb1; | ||
| 1987 | rbuf[3] = 0x3c; | ||
| 1988 | if (ata_id_major_version(args->id) > 7) { | ||
| 1989 | rbuf[4] = args->id[217] >> 8; | ||
| 1990 | rbuf[5] = args->id[217]; | ||
| 1991 | rbuf[7] = args->id[168] & 0xf; | ||
| 1992 | } | ||
| 1993 | |||
| 1994 | return 0; | ||
| 1995 | } | ||
| 1996 | |||
| 1903 | /** | 1997 | /** |
| 1904 | * ata_scsiop_noop - Command handler that simply returns success. | 1998 | * ata_scsiop_noop - Command handler that simply returns success. |
| 1905 | * @args: device IDENTIFY data / SCSI command of interest. | 1999 | * @args: device IDENTIFY data / SCSI command of interest. |
| @@ -2921,6 +3015,9 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd, | |||
| 2921 | case 0x89: | 3015 | case 0x89: |
| 2922 | ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89); | 3016 | ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89); |
| 2923 | break; | 3017 | break; |
| 3018 | case 0xb1: | ||
| 3019 | ata_scsi_rbuf_fill(&args, ata_scsiop_inq_b1); | ||
| 3020 | break; | ||
| 2924 | default: | 3021 | default: |
| 2925 | ata_scsi_invalid_field(cmd, done); | 3022 | ata_scsi_invalid_field(cmd, done); |
| 2926 | break; | 3023 | break; |
