From: Erik Andersen <andersen@codepoet.org>
To: Jeff Garzik <jeff@garzik.org>
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH] support HDIO_GET_IDENTITY in libata
Date: Thu, 14 Dec 2006 13:26:08 -0700 [thread overview]
Message-ID: <20061214202608.GA2313@codepoet.org> (raw)
In-Reply-To: <4581AEA0.3040708@garzik.org>
On Thu Dec 14, 2006 at 03:05:52PM -0500, Jeff Garzik wrote:
> FWIW, libata generally follows a "implement it, if enough people care
> about it" policy for the old HDIO_xxx ioctls.
I personally care about HDIO_GET_IDENTITY and find it terribly
useful to quickly find out about a drive. Perhaps enough other
people care about this ioctl that it might make it into the official
libata tree. Well tested with a number of months of use.
Signed-off-by: Erik Andersen <andersen@codepoet.org>
-Erik
--
Erik B. Andersen http://codepoet-consulting.com/
--This message was written using 73% post-consumer electrons--
--- orig/drivers/ata/libata-scsi.c 2006-10-16 16:50:50.000000000 -0600
+++ linux-2.6.18/drivers/ata/libata-scsi.c 2006-10-16 16:50:50.000000000 -0600
@@ -303,6 +303,172 @@
return rc;
}
+static void ide_fixstring (u8 *s, const int bytecount)
+{
+ u8 *p = s, *end = &s[bytecount & ~1]; /* bytecount must be even */
+
+#ifndef __BIG_ENDIAN
+# ifdef __LITTLE_ENDIAN
+ /* convert from big-endian to host byte order */
+ for (p = end ; p != s;) {
+ unsigned short *pp = (unsigned short *) (p -= 2);
+ *pp = ntohs(*pp);
+ }
+# else
+# error "Please fix <asm/byteorder.h>"
+# endif
+#endif
+ /* strip leading blanks */
+ while (s != end && *s == ' ')
+ ++s;
+ /* compress internal blanks and strip trailing blanks */
+ while (s != end && *s) {
+ if (*s++ != ' ' || (s != end && *s && *s != ' '))
+ *p++ = *(s-1);
+ }
+ /* wipe out trailing garbage */
+ while (p != end)
+ *p++ = '\0';
+}
+
+static void ide_fix_driveid (struct hd_driveid *id)
+{
+#ifndef __LITTLE_ENDIAN
+# ifdef __BIG_ENDIAN
+ int i;
+ u16 *stringcast;
+
+ id->config = __le16_to_cpu(id->config);
+ id->cyls = __le16_to_cpu(id->cyls);
+ id->reserved2 = __le16_to_cpu(id->reserved2);
+ id->heads = __le16_to_cpu(id->heads);
+ id->track_bytes = __le16_to_cpu(id->track_bytes);
+ id->sector_bytes = __le16_to_cpu(id->sector_bytes);
+ id->sectors = __le16_to_cpu(id->sectors);
+ id->vendor0 = __le16_to_cpu(id->vendor0);
+ id->vendor1 = __le16_to_cpu(id->vendor1);
+ id->vendor2 = __le16_to_cpu(id->vendor2);
+ stringcast = (u16 *)&id->serial_no[0];
+ for (i = 0; i < (20/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ id->buf_type = __le16_to_cpu(id->buf_type);
+ id->buf_size = __le16_to_cpu(id->buf_size);
+ id->ecc_bytes = __le16_to_cpu(id->ecc_bytes);
+ stringcast = (u16 *)&id->fw_rev[0];
+ for (i = 0; i < (8/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ stringcast = (u16 *)&id->model[0];
+ for (i = 0; i < (40/2); i++)
+ stringcast[i] = __le16_to_cpu(stringcast[i]);
+ id->dword_io = __le16_to_cpu(id->dword_io);
+ id->reserved50 = __le16_to_cpu(id->reserved50);
+ id->field_valid = __le16_to_cpu(id->field_valid);
+ id->cur_cyls = __le16_to_cpu(id->cur_cyls);
+ id->cur_heads = __le16_to_cpu(id->cur_heads);
+ id->cur_sectors = __le16_to_cpu(id->cur_sectors);
+ id->cur_capacity0 = __le16_to_cpu(id->cur_capacity0);
+ id->cur_capacity1 = __le16_to_cpu(id->cur_capacity1);
+ id->lba_capacity = __le32_to_cpu(id->lba_capacity);
+ id->dma_1word = __le16_to_cpu(id->dma_1word);
+ id->dma_mword = __le16_to_cpu(id->dma_mword);
+ id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes);
+ id->eide_dma_min = __le16_to_cpu(id->eide_dma_min);
+ id->eide_dma_time = __le16_to_cpu(id->eide_dma_time);
+ id->eide_pio = __le16_to_cpu(id->eide_pio);
+ id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);
+ for (i = 0; i < 2; ++i)
+ id->words69_70[i] = __le16_to_cpu(id->words69_70[i]);
+ for (i = 0; i < 4; ++i)
+ id->words71_74[i] = __le16_to_cpu(id->words71_74[i]);
+ id->queue_depth = __le16_to_cpu(id->queue_depth);
+ for (i = 0; i < 4; ++i)
+ id->words76_79[i] = __le16_to_cpu(id->words76_79[i]);
+ id->major_rev_num = __le16_to_cpu(id->major_rev_num);
+ id->minor_rev_num = __le16_to_cpu(id->minor_rev_num);
+ id->command_set_1 = __le16_to_cpu(id->command_set_1);
+ id->command_set_2 = __le16_to_cpu(id->command_set_2);
+ id->cfsse = __le16_to_cpu(id->cfsse);
+ id->cfs_enable_1 = __le16_to_cpu(id->cfs_enable_1);
+ id->cfs_enable_2 = __le16_to_cpu(id->cfs_enable_2);
+ id->csf_default = __le16_to_cpu(id->csf_default);
+ id->dma_ultra = __le16_to_cpu(id->dma_ultra);
+ id->trseuc = __le16_to_cpu(id->trseuc);
+ id->trsEuc = __le16_to_cpu(id->trsEuc);
+ id->CurAPMvalues = __le16_to_cpu(id->CurAPMvalues);
+ id->mprc = __le16_to_cpu(id->mprc);
+ id->hw_config = __le16_to_cpu(id->hw_config);
+ id->acoustic = __le16_to_cpu(id->acoustic);
+ id->msrqs = __le16_to_cpu(id->msrqs);
+ id->sxfert = __le16_to_cpu(id->sxfert);
+ id->sal = __le16_to_cpu(id->sal);
+ id->spg = __le32_to_cpu(id->spg);
+ id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2);
+ for (i = 0; i < 22; i++)
+ id->words104_125[i] = __le16_to_cpu(id->words104_125[i]);
+ id->last_lun = __le16_to_cpu(id->last_lun);
+ id->word127 = __le16_to_cpu(id->word127);
+ id->dlf = __le16_to_cpu(id->dlf);
+ id->csfo = __le16_to_cpu(id->csfo);
+ for (i = 0; i < 26; i++)
+ id->words130_155[i] = __le16_to_cpu(id->words130_155[i]);
+ id->word156 = __le16_to_cpu(id->word156);
+ for (i = 0; i < 3; i++)
+ id->words157_159[i] = __le16_to_cpu(id->words157_159[i]);
+ id->cfa_power = __le16_to_cpu(id->cfa_power);
+ for (i = 0; i < 14; i++)
+ id->words161_175[i] = __le16_to_cpu(id->words161_175[i]);
+ for (i = 0; i < 31; i++)
+ id->words176_205[i] = __le16_to_cpu(id->words176_205[i]);
+ for (i = 0; i < 48; i++)
+ id->words206_254[i] = __le16_to_cpu(id->words206_254[i]);
+ id->integrity_word = __le16_to_cpu(id->integrity_word);
+# else
+# error "Please fix <asm/byteorder.h>"
+# endif
+#endif
+ ide_fixstring(id->model, sizeof(id->model));
+ ide_fixstring(id->fw_rev, sizeof(id->fw_rev));
+ ide_fixstring(id->serial_no, sizeof(id->serial_no));
+}
+
+/**
+ * ata_identify_ioctl - Handler for HDIO_GET_IDENTITY ioctl
+ * @scsidev: Device to which we are issuing command
+ * @id: a SECTOR_SIZE buffer in which to return the ATA identity
+ *
+ * LOCKING:
+ * Defined by the SCSI layer. We don't really care.
+ *
+ * RETURNS:
+ * Zero on success, negative errno on error.
+ */
+int ata_identify_ioctl(struct scsi_device *scsidev, int cmd, u8 *argbuf)
+{
+ int rc = 0;
+ u8 scsi_cmd[MAX_COMMAND_SIZE];
+ struct scsi_sense_hdr sshdr;
+ struct hd_driveid *id;
+
+ memset(scsi_cmd, 0, sizeof(scsi_cmd));
+ scsi_cmd[0] = ATA_16;
+ scsi_cmd[1] = (4 << 1); /* PIO Data-in */
+ scsi_cmd[2] = 0x0e; /* no off.line or cc, read from dev,
+ block count in sector count field */
+ scsi_cmd[14] = cmd; /* WIN_IDENTIFY or WIN_PIDENTIFY */
+
+ /* Good values for timeout and retries? Values below
+ from scsi_ioctl_send_command() for default case... */
+ if (scsi_execute_req(scsidev, scsi_cmd, DMA_FROM_DEVICE,
+ argbuf, SECTOR_SIZE, &sshdr, (10*HZ), 5))
+ rc = -EIO;
+
+ /* Need code to retrieve data from check condition? */
+ id = (struct hd_driveid *) argbuf;
+ ide_fix_driveid(id);
+
+ return rc;
+}
+
int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
{
int val = -EINVAL, rc = -EINVAL;
@@ -330,6 +496,45 @@
return -EACCES;
return ata_task_ioctl(scsidev, arg);
+ case HDIO_GET_IDENTITY:
+ case HDIO_OBSOLETE_IDENTITY:
+ {
+ u8 *argbuf;
+ int ret, idcmd;
+ struct ata_port *ap;
+ struct ata_device *dev;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EACCES;
+
+ ap = (struct ata_port *) &scsidev->host->hostdata[0];
+ if (!ap)
+ return -ENODEV;
+
+ dev = ata_scsi_find_dev(ap, scsidev);
+ if (!dev)
+ return -ENODEV;
+
+ argbuf = kmalloc(SECTOR_SIZE, GFP_KERNEL);
+ if (NULL == (void *)argbuf) {
+ return -ENOMEM;
+ }
+
+ idcmd = WIN_IDENTIFY;
+ if (!atapi_enabled && dev->class == ATA_DEV_ATAPI) {
+ idcmd = WIN_PIDENTIFY;
+ }
+ ret = ata_identify_ioctl(scsidev, idcmd, argbuf);
+ if (ret!=0 || copy_to_user((char *)arg, (char *)argbuf,
+ (cmd == HDIO_GET_IDENTITY) ?
+ sizeof(struct hd_driveid) : 142))
+ {
+ ret = -EFAULT;
+ }
+ kfree(argbuf);
+ return ret;
+ }
+
default:
rc = -ENOTTY;
break;
next prev parent reply other threads:[~2006-12-14 20:26 UTC|newest]
Thread overview: 78+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-12-14 2:06 Linux 2.6.20-rc1 Linus Torvalds
2006-12-14 2:46 ` Gene Heskett
2006-12-14 3:32 ` Linus Torvalds
2006-12-14 5:36 ` Gene Heskett
2006-12-14 17:48 ` ieee1394 in 2.6.20-rc1 (was Re: Linux 2.6.20-rc1) Stefan Richter
2006-12-14 19:08 ` Stefan Richter
2006-12-15 3:17 ` Gene Heskett
2006-12-17 18:11 ` Gene Heskett
2006-12-17 18:31 ` Stefan Richter
2006-12-17 19:04 ` Gene Heskett
2006-12-17 20:21 ` Stefan Richter
2006-12-17 23:34 ` Gene Heskett
2006-12-18 1:05 ` Stefan Richter
2006-12-18 4:29 ` Gene Heskett
2006-12-18 15:45 ` Stefan Richter
2006-12-18 15:54 ` Gene Heskett
2006-12-14 13:59 ` Linux 2.6.20-rc1 Alessandro Suardi
2006-12-14 14:18 ` Steve WIse
2006-12-14 15:48 ` Alan
2006-12-14 19:30 ` Alistair John Strachan
2006-12-14 19:57 ` Linus Torvalds
2006-12-14 20:05 ` Jeff Garzik
2006-12-14 20:26 ` Erik Andersen [this message]
2006-12-14 20:31 ` [PATCH] support HDIO_GET_IDENTITY in libata Jeff Garzik
2006-12-14 20:40 ` Erik Andersen
2006-12-16 16:34 ` Jeff Garzik
2006-12-15 18:45 ` Alexey Dobriyan
2006-12-16 16:34 ` Jeff Garzik
2006-12-14 20:16 ` Linux 2.6.20-rc1 Alistair John Strachan
2006-12-14 20:28 ` Jens Axboe
2006-12-14 20:33 ` Jeff Garzik
2006-12-14 20:36 ` Jens Axboe
2006-12-14 20:48 ` Jens Axboe
2006-12-14 21:13 ` Alistair John Strachan
2006-12-14 21:20 ` Jens Axboe
2006-12-15 0:48 ` Alistair John Strachan
2006-12-15 1:41 ` Alistair John Strachan
2006-12-16 21:36 ` Linus Torvalds
2006-12-16 22:28 ` Alistair John Strachan
2006-12-16 22:31 ` Jeff Garzik
2006-12-16 23:00 ` Alistair John Strachan
2006-12-18 18:32 ` Jens Axboe
2006-12-18 18:41 ` Jens Axboe
2006-12-14 21:33 ` Jeff Garzik
2006-12-14 21:44 ` Alistair John Strachan
2006-12-14 21:50 ` Jeff Garzik
2006-12-14 22:33 ` Alistair John Strachan
2006-12-19 12:41 ` Jens Axboe
2006-12-19 14:32 ` Robert Hancock
2006-12-19 14:38 ` Jens Axboe
2006-12-19 14:50 ` Jens Axboe
2006-12-19 17:49 ` Linus Torvalds
2006-12-14 21:53 ` Jeff Garzik
2006-12-14 20:32 ` Nicolas Mailhot
2006-12-14 23:22 ` Jeff Garzik
2006-12-14 23:33 ` Nicolas Mailhot
2006-12-15 16:50 ` Bill Davidsen
2006-12-15 17:28 ` Alan
2006-12-18 21:57 ` Bill Davidsen
[not found] ` <20061216174536.GA2753@melchior.yamamaya.is-a-geek.org>
2006-12-16 18:06 ` IO-APIC + timer doesn't work (was: Linux 2.6.20-rc1) Linus Torvalds
[not found] ` <20061216225338.GA2616@melchior.yamamaya.is-a-geek.org>
[not found] ` <20061216230605.GA2789@melchior.yamamaya.is-a-geek.org>
2006-12-16 23:36 ` Linus Torvalds
[not found] ` <20061216235513.GA2424@melchior.yamamaya.is-a-geek.org>
2006-12-17 0:04 ` IO-APIC + timer doesn't work Linus Torvalds
2006-12-17 5:16 ` Eric W. Biederman
2006-12-17 5:22 ` Eric W. Biederman
2006-12-18 6:16 ` Len Brown
2006-12-17 13:10 ` Tobias Diedrich
2006-12-17 17:26 ` Linus Torvalds
2006-12-17 14:57 ` IO-APIC + timer doesn't work (was: Linux 2.6.20-rc1) Tobias Diedrich
2006-12-18 13:14 ` Eric W. Biederman
2006-12-18 15:23 ` Tobias Diedrich
2006-12-18 15:34 ` Tobias Diedrich
2006-12-18 15:43 ` IO-APIC + timer doesn't work Eric W. Biederman
2006-12-19 8:00 ` Yinghai Lu
2006-12-19 11:27 ` Eric W. Biederman
2006-12-20 6:50 ` Yinghai Lu
2006-12-21 19:15 ` Tobias Diedrich
2006-12-21 20:46 ` Eric W. Biederman
2006-12-31 8:29 ` Yinghai Lu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20061214202608.GA2313@codepoet.org \
--to=andersen@codepoet.org \
--cc=jeff@garzik.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome