diff options
author | Tejun Heo <htejun@gmail.com> | 2007-01-02 06:20:07 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-09 17:39:34 -0500 |
commit | 5924b74c1cde5ef0246cf0dfbe689b27ffbe815b (patch) | |
tree | c4f71c6c5b607d01ceef359275cb9868662dbd21 | |
parent | 18d90deb07ed6fc1818b0f0b326ecc788cea514e (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.c | 43 |
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 | */ | ||
162 | static 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 | |||
163 | int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) | 201 | int 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; |