|
@@ -1803,6 +1803,61 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * ata_scsiop_inq_89 - Simulate INQUIRY VPD page 89, ATA info
|
|
|
+ * @args: device IDENTIFY data / SCSI command of interest.
|
|
|
+ * @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
|
|
|
+ * @buflen: Response buffer length.
|
|
|
+ *
|
|
|
+ * Yields SAT-specified ATA VPD page.
|
|
|
+ *
|
|
|
+ * LOCKING:
|
|
|
+ * spin_lock_irqsave(host lock)
|
|
|
+ */
|
|
|
+
|
|
|
+unsigned int ata_scsiop_inq_89(struct ata_scsi_args *args, u8 *rbuf,
|
|
|
+ unsigned int buflen)
|
|
|
+{
|
|
|
+ u8 pbuf[60];
|
|
|
+ struct ata_taskfile tf;
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ if (!buflen)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ memset(&pbuf, 0, sizeof(pbuf));
|
|
|
+ memset(&tf, 0, sizeof(tf));
|
|
|
+
|
|
|
+ pbuf[1] = 0x89; /* our page code */
|
|
|
+ pbuf[2] = (0x238 >> 8); /* page size fixed at 238h */
|
|
|
+ pbuf[3] = (0x238 & 0xff);
|
|
|
+
|
|
|
+ memcpy(&pbuf[8], "ATA ", 8);
|
|
|
+ ata_id_string(args->id, &pbuf[16], ATA_ID_PROD, 16);
|
|
|
+ ata_id_string(args->id, &pbuf[32], ATA_ID_FW_REV, 4);
|
|
|
+
|
|
|
+ /* we don't store the ATA device signature, so we fake it */
|
|
|
+
|
|
|
+ tf.command = ATA_DRDY; /* really, this is Status reg */
|
|
|
+ tf.lbal = 0x1;
|
|
|
+ tf.nsect = 0x1;
|
|
|
+
|
|
|
+ ata_tf_to_fis(&tf, 0, 1, &pbuf[36]); /* TODO: PMP? */
|
|
|
+ pbuf[36] = 0x34; /* force D2H Reg FIS (34h) */
|
|
|
+
|
|
|
+ pbuf[56] = ATA_CMD_ID_ATA;
|
|
|
+
|
|
|
+ i = min(buflen, 60U);
|
|
|
+ memcpy(rbuf, &pbuf[0], i);
|
|
|
+ buflen -= i;
|
|
|
+
|
|
|
+ if (!buflen)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ memcpy(&rbuf[60], &args->id[0], min(buflen, 512U));
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* ata_scsiop_noop - Command handler that simply returns success.
|
|
|
* @args: device IDENTIFY data / SCSI command of interest.
|
|
@@ -2880,14 +2935,23 @@ void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd,
|
|
|
ata_scsi_invalid_field(cmd, done);
|
|
|
else if ((scsicmd[1] & 1) == 0) /* is EVPD clear? */
|
|
|
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_std);
|
|
|
- else if (scsicmd[2] == 0x00)
|
|
|
+ else switch (scsicmd[2]) {
|
|
|
+ case 0x00:
|
|
|
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_00);
|
|
|
- else if (scsicmd[2] == 0x80)
|
|
|
+ break;
|
|
|
+ case 0x80:
|
|
|
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_80);
|
|
|
- else if (scsicmd[2] == 0x83)
|
|
|
+ break;
|
|
|
+ case 0x83:
|
|
|
ata_scsi_rbuf_fill(&args, ata_scsiop_inq_83);
|
|
|
- else
|
|
|
+ break;
|
|
|
+ case 0x89:
|
|
|
+ ata_scsi_rbuf_fill(&args, ata_scsiop_inq_89);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
ata_scsi_invalid_field(cmd, done);
|
|
|
+ break;
|
|
|
+ }
|
|
|
break;
|
|
|
|
|
|
case MODE_SENSE:
|