Skip to content

Commit

Permalink
[libata] SCSI: support INQUIRY page 89h (ATA info page)
Browse files Browse the repository at this point in the history
Signed-off-by: Jeff Garzik <jeff@garzik.org>
  • Loading branch information
Jeff Garzik committed Oct 12, 2007
1 parent d4155e6 commit ad355b4
Showing 1 changed file with 68 additions and 4 deletions.
72 changes: 68 additions & 4 deletions drivers/ata/libata-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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:
Expand Down

0 comments on commit ad355b4

Please sign in to comment.