Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Tejun Heo and committed by
Jeff Garzik
5924b74c 18d90deb

+42 -1
+42 -1
drivers/ata/libata-scsi.c
··· 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 191 * ata_cmd_ioctl - Handler for HDIO_DRIVE_CMD ioctl 153 192 * @scsidev: Device to which we are issuing command 154 193 * @arg: User provided data for issuing command ··· 198 159 * RETURNS: 199 160 * Zero on success, negative errno on error. 200 161 */ 201 - 202 162 int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg) 203 163 { 204 164 int rc = 0; ··· 396 358 if (val != 0) 397 359 return -EINVAL; 398 360 return 0; 361 + 362 + case HDIO_GET_IDENTITY: 363 + return ata_get_identity(scsidev, arg); 399 364 400 365 case HDIO_DRIVE_CMD: 401 366 if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))