aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r--drivers/ide/ide.c59
1 files changed, 51 insertions, 8 deletions
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 8d3fab33a3c7..21b3a767e7d7 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -328,7 +328,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
328 if (arg < 0 || arg > 1) 328 if (arg < 0 || arg > 1)
329 return -EINVAL; 329 return -EINVAL;
330 330
331 if ((drive->driveid->capability & 1) == 0) 331 if (ata_id_has_dma(drive->id) == 0)
332 goto out; 332 goto out;
333 333
334 if (hwif->dma_ops == NULL) 334 if (hwif->dma_ops == NULL)
@@ -502,12 +502,60 @@ static int generic_drive_reset(ide_drive_t *drive)
502 return ret; 502 return ret;
503} 503}
504 504
505static inline void ide_id_to_hd_driveid(u16 *id)
506{
507#ifdef __BIG_ENDIAN
508 /* accessed in struct hd_driveid as 8-bit values */
509 id[ATA_ID_MAX_MULTSECT] = __cpu_to_le16(id[ATA_ID_MAX_MULTSECT]);
510 id[ATA_ID_CAPABILITY] = __cpu_to_le16(id[ATA_ID_CAPABILITY]);
511 id[ATA_ID_OLD_PIO_MODES] = __cpu_to_le16(id[ATA_ID_OLD_PIO_MODES]);
512 id[ATA_ID_OLD_DMA_MODES] = __cpu_to_le16(id[ATA_ID_OLD_DMA_MODES]);
513 id[ATA_ID_MULTSECT] = __cpu_to_le16(id[ATA_ID_MULTSECT]);
514
515 /* as 32-bit values */
516 *(u32 *)&id[ATA_ID_LBA_CAPACITY] = ata_id_u32(id, ATA_ID_LBA_CAPACITY);
517 *(u32 *)&id[ATA_ID_SPG] = ata_id_u32(id, ATA_ID_SPG);
518
519 /* as 64-bit value */
520 *(u64 *)&id[ATA_ID_LBA_CAPACITY_2] =
521 ata_id_u64(id, ATA_ID_LBA_CAPACITY_2);
522#endif
523}
524
525static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,
526 unsigned long arg)
527{
528 u16 *id = NULL;
529 int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142;
530 int rc = 0;
531
532 if (drive->id_read == 0) {
533 rc = -ENOMSG;
534 goto out;
535 }
536
537 id = kmalloc(size, GFP_KERNEL);
538 if (id == NULL) {
539 rc = -ENOMEM;
540 goto out;
541 }
542
543 memcpy(id, drive->id, size);
544 ide_id_to_hd_driveid(id);
545
546 if (copy_to_user((void __user *)arg, id, size))
547 rc = -EFAULT;
548
549 kfree(id);
550out:
551 return rc;
552}
553
505int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, 554int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
506 unsigned int cmd, unsigned long arg) 555 unsigned int cmd, unsigned long arg)
507{ 556{
508 unsigned long flags; 557 unsigned long flags;
509 ide_driver_t *drv; 558 ide_driver_t *drv;
510 void __user *p = (void __user *)arg;
511 int err = 0, (*setfunc)(ide_drive_t *, int); 559 int err = 0, (*setfunc)(ide_drive_t *, int);
512 u8 *val; 560 u8 *val;
513 561
@@ -528,12 +576,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
528 case HDIO_GET_IDENTITY: 576 case HDIO_GET_IDENTITY:
529 if (bdev != bdev->bd_contains) 577 if (bdev != bdev->bd_contains)
530 return -EINVAL; 578 return -EINVAL;
531 if (drive->id_read == 0) 579 return ide_get_identity_ioctl(drive, cmd, arg);
532 return -ENOMSG;
533 if (copy_to_user(p, drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
534 return -EFAULT;
535 return 0;
536
537 case HDIO_GET_NICE: 580 case HDIO_GET_NICE:
538 return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP | 581 return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP |
539 drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP | 582 drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP |