summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@redhat.com>2004-05-16 13:33:18 -0400
committerJeff Garzik <jgarzik@redhat.com>2004-05-16 13:33:18 -0400
commit7f594e47663f5121d34ffdf43eba8a8109bd1be7 (patch)
tree333c7f596b0445a16a326e8066630cec1b446cc2
parente9c8846e3de355918b6ee6df1bb5b270c0963199 (diff)
[libata] SCSI->ATA simulator hacking: INQUIRY command
The SCSI T10 committee is working on a document describing a standard method for translating ATA<->SCSI, since it being done quite often these days. Some of the recommendations are reasonable, and we implement two here: * Mirror that ATA 'removeable media' bit into INQUIRY output. * Change behavior of INQUIRY output field 'product revision' from the libata software version number to the first 4 bytes of the ATA device's firmware revision number. Rather than cache the firmware revision in struct ata_device, as was/is done with two other strings, I took the opportunity to eliminate the caching of the two other strings, 'vendor' and 'product'. These strings are now retrieved as needed from the IDENTIFY [PACKET] DEVICE info page, since we cache its entire contents. Retrieving a string from the identify-device page is done via the helper function ata_dev_id_string(), which is now exported. This patch winds up making struct ata_device 40 bytes smaller, and the libata core gets a bit smaller as well.
-rw-r--r--drivers/scsi/libata-core.c28
-rw-r--r--drivers/scsi/libata-scsi.c16
-rw-r--r--drivers/scsi/libata.h2
-rw-r--r--drivers/scsi/sata_sil.c10
-rw-r--r--include/linux/ata.h2
-rw-r--r--include/linux/libata.h8
6 files changed, 26 insertions, 40 deletions
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 9c4117cb6a6e..208ffa62518c 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -818,7 +818,7 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
* @dev: Device whose IDENTIFY DEVICE results we will examine
* @s: string into which data is output
* @ofs: offset into identify device page
- * @len: length of string to return
+ * @len: length of string to return. must be an even number.
*
* The strings in the IDENTIFY DEVICE page are broken up into
* 16-bit chunks. Run through the string, and output each
@@ -848,29 +848,6 @@ void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
}
/**
- * ata_dev_parse_strings - Store useful IDENTIFY DEVICE page strings
- * @dev: Device whose IDENTIFY DEVICE page info we use
- *
- * We store 'vendor' and 'product' strings read from the device,
- * for later use in the SCSI simulator's INQUIRY data.
- *
- * Set these strings here, in the case of 'product', using
- * data read from the ATA IDENTIFY DEVICE page.
- *
- * LOCKING:
- * caller.
- */
-
-static void ata_dev_parse_strings(struct ata_device *dev)
-{
- assert (dev->class == ATA_DEV_ATA);
- memcpy(dev->vendor, "ATA ", 8);
-
- ata_dev_id_string(dev, dev->product, ATA_ID_PROD_OFS,
- sizeof(dev->product));
-}
-
-/**
* __ata_dev_select - Select device 0/1 on ATA bus
* @ap: ATA channel to manipulate
* @device: ATA device (numbered from zero) to select
@@ -1127,8 +1104,6 @@ retry:
ata_dump_id(dev);
- ata_dev_parse_strings(dev);
-
/* ATA-specific feature tests */
if (dev->class == ATA_DEV_ATA) {
if (!ata_id_is_ata(dev)) /* sanity check */
@@ -3525,3 +3500,4 @@ EXPORT_SYMBOL_GPL(ata_scsi_error);
EXPORT_SYMBOL_GPL(ata_scsi_slave_config);
EXPORT_SYMBOL_GPL(ata_scsi_release);
EXPORT_SYMBOL_GPL(ata_host_intr);
+EXPORT_SYMBOL_GPL(ata_dev_id_string);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index c1d5e03adfe1..b5ce68fa1a6b 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -498,7 +498,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
unsigned int buflen)
{
- const u8 hdr[] = {
+ struct ata_device *dev = args->dev;
+
+ u8 hdr[] = {
TYPE_DISK,
0,
0x5, /* claim SPC-3 version compatibility */
@@ -506,14 +508,20 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
96 - 4
};
+ /* set scsi removeable (RMB) bit per ata bit */
+ if (ata_id_removeable(dev))
+ hdr[1] |= (1 << 7);
+
VPRINTK("ENTER\n");
memcpy(rbuf, hdr, sizeof(hdr));
if (buflen > 36) {
- memcpy(&rbuf[8], args->dev->vendor, 8);
- memcpy(&rbuf[16], args->dev->product, 16);
- memcpy(&rbuf[32], DRV_VERSION, 4);
+ memcpy(&rbuf[8], "ATA ", 8);
+ ata_dev_id_string(dev, &rbuf[16], ATA_ID_PROD_OFS, 16);
+ ata_dev_id_string(dev, &rbuf[32], ATA_ID_FW_REV_OFS, 4);
+ if (rbuf[32] == 0 || rbuf[32] == ' ')
+ memcpy(&rbuf[32], "n/a ", 4);
}
if (buflen > 63) {
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index cf7bb8d6116b..460c72c1b80d 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -36,8 +36,6 @@ struct ata_scsi_args {
};
/* libata-core.c */
-extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
- unsigned int ofs, unsigned int len);
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev);
extern int ata_qc_issue(struct ata_queued_cmd *qc);
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index f21d3aa00629..93bad1475921 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -276,8 +276,14 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
static void sil_dev_config(struct ata_port *ap, struct ata_device *dev)
{
unsigned int n, quirks = 0;
- const char *s = &dev->product[0];
- unsigned int len = strnlen(s, sizeof(dev->product));
+ unsigned char model_num[40];
+ const char *s;
+ unsigned int len;
+
+ ata_dev_id_string(dev, model_num, ATA_ID_PROD_OFS,
+ sizeof(model_num));
+ s = &model_num[0];
+ len = strnlen(s, sizeof(model_num));
/* ATAPI specifies that empty space is blank-filled; remove blanks */
while ((len > 0) && (s[len - 1] == ' '))
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 053fd4b64da6..4459a429ba0a 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -38,6 +38,7 @@ enum {
ATA_ID_WORDS = 256,
ATA_ID_PROD_OFS = 27,
+ ATA_ID_FW_REV_OFS = 23,
ATA_ID_SERNO_OFS = 10,
ATA_ID_MAJOR_VER = 80,
ATA_ID_PIO_MODES = 64,
@@ -205,6 +206,7 @@ struct ata_taskfile {
#define ata_id_has_wcache(dev) ((dev)->id[82] & (1 << 5))
#define ata_id_has_lba(dev) ((dev)->id[49] & (1 << 8))
#define ata_id_has_dma(dev) ((dev)->id[49] & (1 << 9))
+#define ata_id_removeable(dev) ((dev)->id[0] & (1 << 7))
#define ata_id_u32(dev,n) \
(((u32) (dev)->id[(n) + 1] << 16) | ((u32) (dev)->id[(n)]))
#define ata_id_u64(dev,n) \
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 077f6461ab2a..388d149cf202 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -260,12 +260,6 @@ struct ata_device {
unsigned int pio_mode;
unsigned int udma_mode;
- unsigned char vendor[8]; /* space-padded, not ASCIIZ */
- unsigned char product[32]; /* WARNING: shorter than
- * ATAPI7 spec size, 40 ASCII
- * characters
- */
-
/* cache info about current transfer mode */
u8 xfer_protocol; /* taskfile xfer protocol */
u8 read_cmd; /* opcode to use on read */
@@ -398,6 +392,8 @@ extern int ata_port_start (struct ata_port *ap);
extern void ata_port_stop (struct ata_port *ap);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
extern void ata_fill_sg(struct ata_queued_cmd *qc);
+extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
+ unsigned int ofs, unsigned int len);
extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc);
extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc);
extern void ata_bmdma_setup_pio (struct ata_queued_cmd *qc);