aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-01-02 06:20:07 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-09 17:39:34 -0500
commit5924b74c1cde5ef0246cf0dfbe689b27ffbe815b (patch)
treec4f71c6c5b607d01ceef359275cb9868662dbd21
parent18d90deb07ed6fc1818b0f0b326ecc788cea514e (diff)
libata: implement HDIO_GET_IDENTITY
'hdparm -I' doesn't work with ATAPI devices and sg_sat is not widely spread yet leaving no easy way to access ATAPI IDENTIFY data. Implement HDIO_GET_IDENTITY such that at least 'hdparm -i' works. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/libata-scsi.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 9b5088ab2742..cc229e31432f 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -149,6 +149,45 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
149} 149}
150 150
151/** 151/**
152 * ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl
153 * @sdev: SCSI device to get identify data for
154 * @arg: User buffer area for identify data
155 *
156 * LOCKING:
157 * Defined by the SCSI layer. We don't really care.
158 *
159 * RETURNS:
160 * Zero on success, negative errno on error.
161 */
162static int ata_get_identity(struct scsi_device *sdev, void __user *arg)
163{
164 struct ata_port *ap = ata_shost_to_port(sdev->host);
165 struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
166 u16 __user *dst = arg;
167 char buf[40];
168
169 if (!dev)
170 return -ENOMSG;
171
172 if (copy_to_user(dst, dev->id, ATA_ID_WORDS * sizeof(u16)))
173 return -EFAULT;
174
175 ata_id_string(dev->id, buf, ATA_ID_PROD, ATA_ID_PROD_LEN);
176 if (copy_to_user(dst + ATA_ID_PROD, buf, ATA_ID_PROD_LEN))
177 return -EFAULT;
178
179 ata_id_string(dev->id, buf, ATA_ID_FW_REV, ATA_ID_FW_REV_LEN);
180 if (copy_to_user(dst + ATA_ID_FW_REV, buf, ATA_ID_FW_REV_LEN))
181 return -EFAULT;
182
183 ata_id_string(dev->id, buf, ATA_ID_SERNO, ATA_ID_SERNO_LEN);
184 if (copy_to_user(dst + ATA_ID_SERNO, buf, ATA_ID_SERNO_LEN))
185 return -EFAULT;
186
187 return 0;
188}
189
190/**
152 * ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl 191 * ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl
153 * @scsidev: Device to which we are issuing command 192 * @scsidev: Device to which we are issuing command
154 * @arg: User provided data for issuing command 193 * @arg: User provided data for issuing command
@@ -159,7 +198,6 @@ int ata_std_bios_param(struct scsi_device *sdev, struct block_device *bdev,
159 * RETURNS: 198 * RETURNS:
160 * Zero on success, negative errno on error. 199 * Zero on success, negative errno on error.
161 */ 200 */
162
163int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) 201int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg)
164{ 202{
165 int rc = 0; 203 int rc = 0;
@@ -359,6 +397,9 @@ int ata_scsi_ioctl(struct scsi_device *scsidev, int cmd, void __user *arg)
359 return -EINVAL; 397 return -EINVAL;
360 return 0; 398 return 0;
361 399
400 case HDIO_GET_IDENTITY:
401 return ata_get_identity(scsidev, arg);
402
362 case HDIO_DRIVE_CMD: 403 case HDIO_DRIVE_CMD:
363 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) 404 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
364 return -EACCES; 405 return -EACCES;