diff options
Diffstat (limited to 'drivers/ide/ide.c')
-rw-r--r-- | drivers/ide/ide.c | 59 |
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 | ||
505 | static 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 | |||
525 | static 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); | ||
550 | out: | ||
551 | return rc; | ||
552 | } | ||
553 | |||
505 | int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, | 554 | int 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 | |