diff options
Diffstat (limited to 'drivers/ide/ide-ioctls.c')
| -rw-r--r-- | drivers/ide/ide-ioctls.c | 77 |
1 files changed, 36 insertions, 41 deletions
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index 1be263eb9c0..6233fa2cb8a 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c @@ -2,8 +2,10 @@ * IDE ioctls handling. */ +#include <linux/export.h> #include <linux/hdreg.h> #include <linux/ide.h> +#include <linux/slab.h> static const struct ide_ioctl_devset ide_ioctl_settings[] = { { HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit }, @@ -64,7 +66,8 @@ static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd, goto out; } - id = kmalloc(size, GFP_KERNEL); + /* ata_id_to_hd_driveid() relies on 'id' to be fully allocated. */ + id = kmalloc(ATA_ID_WORDS * 2, GFP_KERNEL); if (id == NULL) { rc = -ENOMEM; goto out; @@ -111,14 +114,13 @@ static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg) return 0; } -static int ide_cmd_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg) +static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg) { u8 *buf = NULL; int bufsize = 0, err = 0; u8 args[4], xfer_rate = 0; - ide_task_t tfargs; - struct ide_taskfile *tf = &tfargs.tf; - u16 *id = drive->id; + struct ide_cmd cmd; + struct ide_taskfile *tf = &cmd.tf; if (NULL == (void *) arg) { struct request *rq; @@ -134,24 +136,25 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg) if (copy_from_user(args, (void __user *)arg, 4)) return -EFAULT; - memset(&tfargs, 0, sizeof(ide_task_t)); + memset(&cmd, 0, sizeof(cmd)); tf->feature = args[2]; if (args[0] == ATA_CMD_SMART) { tf->nsect = args[3]; tf->lbal = args[1]; - tf->lbam = 0x4f; - tf->lbah = 0xc2; - tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT; + tf->lbam = ATA_SMART_LBAM_PASS; + tf->lbah = ATA_SMART_LBAH_PASS; + cmd.valid.out.tf = IDE_VALID_OUT_TF; + cmd.valid.in.tf = IDE_VALID_NSECT; } else { tf->nsect = args[1]; - tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE | - IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT; + cmd.valid.out.tf = IDE_VALID_FEATURE | IDE_VALID_NSECT; + cmd.valid.in.tf = IDE_VALID_NSECT; } tf->command = args[0]; - tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA; + cmd.protocol = args[3] ? ATA_PROT_PIO : ATA_PROT_NODATA; if (args[3]) { - tfargs.tf_flags |= IDE_TFLAG_IO_16BIT; + cmd.tf_flags |= IDE_TFLAG_IO_16BIT; bufsize = SECTOR_SIZE * args[3]; buf = kzalloc(bufsize, GFP_KERNEL); if (buf == NULL) @@ -160,29 +163,21 @@ static int ide_cmd_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg) if (tf->command == ATA_CMD_SET_FEATURES && tf->feature == SETFEATURES_XFER && - tf->nsect >= XFER_SW_DMA_0 && - (id[ATA_ID_UDMA_MODES] || - id[ATA_ID_MWDMA_MODES] || - id[ATA_ID_SWDMA_MODES])) { - xfer_rate = args[1]; - if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) { - printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot " - "be set\n", drive->name); + tf->nsect >= XFER_SW_DMA_0) { + xfer_rate = ide_find_dma_mode(drive, tf->nsect); + if (xfer_rate != tf->nsect) { + err = -EINVAL; goto abort; } + + cmd.tf_flags |= IDE_TFLAG_SET_XFER; } - err = ide_raw_taskfile(drive, &tfargs, buf, args[3]); + err = ide_raw_taskfile(drive, &cmd, buf, args[3]); args[0] = tf->status; args[1] = tf->error; args[2] = tf->nsect; - - if (!err && xfer_rate) { - /* active-retuning-calls future */ - ide_set_xfer_rate(drive, xfer_rate); - ide_driveid_update(drive); - } abort: if (copy_to_user((void __user *)arg, &args, 4)) err = -EFAULT; @@ -194,25 +189,26 @@ abort: return err; } -static int ide_task_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg) +static int ide_task_ioctl(ide_drive_t *drive, unsigned long arg) { void __user *p = (void __user *)arg; int err = 0; u8 args[7]; - ide_task_t task; + struct ide_cmd cmd; if (copy_from_user(args, p, 7)) return -EFAULT; - memset(&task, 0, sizeof(task)); - memcpy(&task.tf_array[7], &args[1], 6); - task.tf.command = args[0]; - task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + memset(&cmd, 0, sizeof(cmd)); + memcpy(&cmd.tf.feature, &args[1], 6); + cmd.tf.command = args[0]; + cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; + cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; - err = ide_no_data_taskfile(drive, &task); + err = ide_no_data_taskfile(drive, &cmd); - args[0] = task.tf.command; - memcpy(&args[1], &task.tf_array[7], 6); + args[0] = cmd.tf.command; + memcpy(&args[1], &cmd.tf.feature, 6); if (copy_to_user(p, args, 7)) err = -EFAULT; @@ -229,7 +225,6 @@ static int generic_drive_reset(ide_drive_t *drive) rq->cmd_type = REQ_TYPE_SPECIAL; rq->cmd_len = 1; rq->cmd[0] = REQ_DRIVE_RESET; - rq->cmd_flags |= REQ_SOFTBARRIER; if (blk_execute_rq(drive->queue, NULL, rq, 1)) ret = rq->errors; blk_put_request(rq); @@ -262,17 +257,17 @@ int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev, if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO)) return -EACCES; if (drive->media == ide_disk) - return ide_taskfile_ioctl(drive, cmd, arg); + return ide_taskfile_ioctl(drive, arg); return -ENOMSG; #endif case HDIO_DRIVE_CMD: if (!capable(CAP_SYS_RAWIO)) return -EACCES; - return ide_cmd_ioctl(drive, cmd, arg); + return ide_cmd_ioctl(drive, arg); case HDIO_DRIVE_TASK: if (!capable(CAP_SYS_RAWIO)) return -EACCES; - return ide_task_ioctl(drive, cmd, arg); + return ide_task_ioctl(drive, arg); case HDIO_DRIVE_RESET: if (!capable(CAP_SYS_ADMIN)) return -EACCES; |
