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; |