diff options
| author | Jeff Garzik <jgarzik@redhat.com> | 2004-05-16 13:33:18 -0400 |
|---|---|---|
| committer | Jeff Garzik <jgarzik@redhat.com> | 2004-05-16 13:33:18 -0400 |
| commit | 7f594e47663f5121d34ffdf43eba8a8109bd1be7 (patch) | |
| tree | 333c7f596b0445a16a326e8066630cec1b446cc2 | |
| parent | e9c8846e3de355918b6ee6df1bb5b270c0963199 (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.c | 28 | ||||
| -rw-r--r-- | drivers/scsi/libata-scsi.c | 16 | ||||
| -rw-r--r-- | drivers/scsi/libata.h | 2 | ||||
| -rw-r--r-- | drivers/scsi/sata_sil.c | 10 | ||||
| -rw-r--r-- | include/linux/ata.h | 2 | ||||
| -rw-r--r-- | include/linux/libata.h | 8 |
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); |
