All of lore.kernel.org
 help / color / mirror / Atom feed
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;

  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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.