* [PATCH 2/4] ide: add ide_setting_ioctl() helper
2008-08-05 16:40 [PATCH 1/4] ide: remove ->bus_state field from ide_hwif_t Bartlomiej Zolnierkiewicz
@ 2008-08-05 16:40 ` Bartlomiej Zolnierkiewicz
2008-08-05 16:40 ` [PATCH 3/4] ide: cleanup generic_ide_ioctl() Bartlomiej Zolnierkiewicz
2008-08-05 16:40 ` [PATCH 4/4] ide: move ioctls handling to ide-ioctls.c Bartlomiej Zolnierkiewicz
2 siblings, 0 replies; 4+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-08-05 16:40 UTC (permalink / raw)
To: linux-ide; +Cc: Bartlomiej Zolnierkiewicz, linux-kernel
* Add struct ide_ioctl_devset representing ioctl device setting.
* Add ide_setting_ioctl() helper for matching given ioctl
and its parameters against table of ioctl device settings.
* Convert ide_setting_ioctl() and idedisk_ioctl() to use
ide_setting_ioctl().
* Un-export ide_setting_mtx.
While at it:
* {get,set}_lba_addressing() -> {get,set}_addressing()
There should be no functional changes caused by this patch.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
---
drivers/ide/ide-disk.c | 57 ++++++++++++++-----------------------------------
drivers/ide/ide.c | 53 +++++++++++++++++++++++++++++----------------
include/linux/ide.h | 14 +++++++++++-
3 files changed, 64 insertions(+), 60 deletions(-)
Index: b/drivers/ide/ide-disk.c
===================================================================
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -682,7 +682,7 @@ static int set_acoustic(ide_drive_t *dri
return 0;
}
-ide_devset_get(lba_addressing, addressing);
+ide_devset_get(addressing, addressing);
/*
* drive->addressing:
@@ -690,7 +690,7 @@ ide_devset_get(lba_addressing, addressin
* 1: 48-bit
* 2: 48-bit capable doing 28-bit
*/
-static int set_lba_addressing(ide_drive_t *drive, int arg)
+static int set_addressing(ide_drive_t *drive, int arg)
{
if (arg < 0 || arg > 2)
return -EINVAL;
@@ -710,7 +710,7 @@ static int set_lba_addressing(ide_drive_
#ifdef CONFIG_IDE_PROC_FS
ide_devset_rw_nolock(acoustic, 0, 254, acoustic);
-ide_devset_rw_nolock(address, 0, 2, lba_addressing);
+ide_devset_rw_nolock(address, 0, 2, addressing);
ide_devset_rw_nolock(multcount, 0, 16, multcount);
ide_devset_rw_nolock(nowerr, 0, 1, nowerr);
ide_devset_rw_nolock(wcache, 0, 1, wcache);
@@ -759,7 +759,7 @@ static void idedisk_setup(ide_drive_t *d
drive->doorlocking = 1;
}
- (void)set_lba_addressing(drive, 1);
+ (void)set_addressing(drive, 1);
if (drive->addressing == 1) {
int max_s = 2048;
@@ -1006,51 +1006,28 @@ static int idedisk_getgeo(struct block_d
return 0;
}
+static const struct ide_ioctl_devset ide_disk_ioctl_settings[] = {
+{ HDIO_GET_ADDRESS, HDIO_SET_ADDRESS, get_addressing, set_addressing },
+{ HDIO_GET_MULTCOUNT, HDIO_SET_MULTCOUNT, get_multcount, set_multcount },
+{ HDIO_GET_NOWERR, HDIO_SET_NOWERR, get_nowerr, set_nowerr },
+{ HDIO_GET_WCACHE, HDIO_SET_WCACHE, get_wcache, set_wcache },
+{ HDIO_GET_ACOUSTIC, HDIO_SET_ACOUSTIC, get_acoustic, set_acoustic },
+{ 0 }
+};
+
static int idedisk_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- unsigned long flags;
struct block_device *bdev = inode->i_bdev;
struct ide_disk_obj *idkp = ide_disk_g(bdev->bd_disk);
ide_drive_t *drive = idkp->drive;
- int err, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int);
+ int err;
- switch (cmd) {
- case HDIO_GET_ADDRESS: getfunc = get_lba_addressing; goto read_val;
- case HDIO_GET_MULTCOUNT: getfunc = get_multcount; goto read_val;
- case HDIO_GET_NOWERR: getfunc = get_nowerr; goto read_val;
- case HDIO_GET_WCACHE: getfunc = get_wcache; goto read_val;
- case HDIO_GET_ACOUSTIC: getfunc = get_acoustic; goto read_val;
- case HDIO_SET_ADDRESS: setfunc = set_lba_addressing; goto set_val;
- case HDIO_SET_MULTCOUNT: setfunc = set_multcount; goto set_val;
- case HDIO_SET_NOWERR: setfunc = set_nowerr; goto set_val;
- case HDIO_SET_WCACHE: setfunc = set_wcache; goto set_val;
- case HDIO_SET_ACOUSTIC: setfunc = set_acoustic; goto set_val;
- }
+ err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_disk_ioctl_settings);
+ if (err != -EOPNOTSUPP)
+ return err;
return generic_ide_ioctl(drive, file, bdev, cmd, arg);
-
-read_val:
- mutex_lock(&ide_setting_mtx);
- spin_lock_irqsave(&ide_lock, flags);
- err = getfunc(drive);
- spin_unlock_irqrestore(&ide_lock, flags);
- mutex_unlock(&ide_setting_mtx);
- return err >= 0 ? put_user(err, (long __user *)arg) : err;
-
-set_val:
- if (bdev != bdev->bd_contains)
- err = -EINVAL;
- else {
- if (!capable(CAP_SYS_ADMIN))
- err = -EACCES;
- else {
- mutex_lock(&ide_setting_mtx);
- err = setfunc(drive, arg);
- mutex_unlock(&ide_setting_mtx);
- }
- }
- return err;
}
static int idedisk_media_changed(struct gendisk *disk)
Index: b/drivers/ide/ide.c
===================================================================
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -250,8 +250,6 @@ void ide_init_port_hw(ide_hwif_t *hwif,
DEFINE_MUTEX(ide_setting_mtx);
-EXPORT_SYMBOL_GPL(ide_setting_mtx);
-
/**
* ide_spin_wait_hwgroup - wait for group
* @drive: drive in the group
@@ -558,23 +556,23 @@ static int ide_set_nice_ioctl(ide_drive_
return 0;
}
+static const struct ide_ioctl_devset ide_ioctl_settings[] = {
+{ HDIO_GET_32BIT, HDIO_SET_32BIT, get_io_32bit, set_io_32bit },
+{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, get_ksettings, set_ksettings },
+{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, get_unmaskirq, set_unmaskirq },
+{ HDIO_GET_DMA, HDIO_SET_DMA, get_using_dma, set_using_dma },
+{ -1, HDIO_SET_PIO_MODE, NULL, set_pio_mode },
+{ 0 }
+};
+
int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
unsigned int cmd, unsigned long arg)
{
- unsigned long flags;
- int err = 0, (*getfunc)(ide_drive_t *), (*setfunc)(ide_drive_t *, int);
+ int err;
- switch (cmd) {
- case HDIO_GET_32BIT: getfunc = get_io_32bit; goto read_val;
- case HDIO_GET_KEEPSETTINGS: getfunc = get_ksettings; goto read_val;
- case HDIO_GET_UNMASKINTR: getfunc = get_unmaskirq; goto read_val;
- case HDIO_GET_DMA: getfunc = get_using_dma; goto read_val;
- case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val;
- case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val;
- case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val;
- case HDIO_SET_UNMASKINTR: setfunc = set_unmaskirq; goto set_val;
- case HDIO_SET_DMA: setfunc = set_using_dma; goto set_val;
- }
+ err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings);
+ if (err != -EOPNOTSUPP)
+ return err;
switch (cmd) {
case HDIO_OBSOLETE_IDENTITY:
@@ -629,11 +627,29 @@ int generic_ide_ioctl(ide_drive_t *drive
default:
return -EINVAL;
}
+}
+EXPORT_SYMBOL(generic_ide_ioctl);
+
+int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
+ unsigned int cmd, unsigned long arg,
+ const struct ide_ioctl_devset *s)
+{
+ unsigned long flags;
+ int err = -EOPNOTSUPP;
+
+ for (; s->get_ioctl; s++) {
+ if (s->get && s->get_ioctl == cmd)
+ goto read_val;
+ else if (s->set && s->set_ioctl == cmd)
+ goto set_val;
+ }
+
+ return err;
read_val:
mutex_lock(&ide_setting_mtx);
spin_lock_irqsave(&ide_lock, flags);
- err = getfunc(drive);
+ err = s->get(drive);
spin_unlock_irqrestore(&ide_lock, flags);
mutex_unlock(&ide_setting_mtx);
return err >= 0 ? put_user(err, (long __user *)arg) : err;
@@ -646,14 +662,13 @@ set_val:
err = -EACCES;
else {
mutex_lock(&ide_setting_mtx);
- err = setfunc(drive, arg);
+ err = s->set(drive, arg);
mutex_unlock(&ide_setting_mtx);
}
}
return err;
}
-
-EXPORT_SYMBOL(generic_ide_ioctl);
+EXPORT_SYMBOL_GPL(ide_setting_ioctl);
/**
* ide_device_get - get an additional reference to a ide_drive_t
Index: b/include/linux/ide.h
===================================================================
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -930,7 +930,19 @@ struct ide_driver_s {
int ide_device_get(ide_drive_t *);
void ide_device_put(ide_drive_t *);
-int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *, unsigned, unsigned long);
+struct ide_ioctl_devset {
+ unsigned int get_ioctl;
+ unsigned int set_ioctl;
+
+ int (*get)(ide_drive_t *);
+ int (*set)(ide_drive_t *, int);
+};
+
+int ide_setting_ioctl(ide_drive_t *, struct block_device *, unsigned int,
+ unsigned long, const struct ide_ioctl_devset *);
+
+int generic_ide_ioctl(ide_drive_t *, struct file *, struct block_device *,
+ unsigned, unsigned long);
extern int ide_vlb_clk;
extern int ide_pci_clk;
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 4/4] ide: move ioctls handling to ide-ioctls.c
2008-08-05 16:40 [PATCH 1/4] ide: remove ->bus_state field from ide_hwif_t Bartlomiej Zolnierkiewicz
2008-08-05 16:40 ` [PATCH 2/4] ide: add ide_setting_ioctl() helper Bartlomiej Zolnierkiewicz
2008-08-05 16:40 ` [PATCH 3/4] ide: cleanup generic_ide_ioctl() Bartlomiej Zolnierkiewicz
@ 2008-08-05 16:40 ` Bartlomiej Zolnierkiewicz
2 siblings, 0 replies; 4+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2008-08-05 16:40 UTC (permalink / raw)
To: linux-ide; +Cc: Bartlomiej Zolnierkiewicz, linux-kernel
* Move ioctls handling to ide-ioctls.c
(except HDIO_DRIVE_TASKFILE for now).
* Make ide_{cmd,task}() static.
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
---
drivers/ide/Makefile | 4
drivers/ide/ide-ioctls.c | 289 +++++++++++++++++++++++++++++++++++++++++++++
drivers/ide/ide-taskfile.c | 109 ----------------
drivers/ide/ide.c | 174 ---------------------------
include/linux/ide.h | 2
5 files changed, 291 insertions(+), 287 deletions(-)
Index: b/drivers/ide/Makefile
===================================================================
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -4,8 +4,8 @@
EXTRA_CFLAGS += -Idrivers/ide
-ide-core-y += ide.o ide-io.o ide-iops.o ide-lib.o ide-probe.o ide-taskfile.o \
- ide-pio-blacklist.o
+ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
+ ide-taskfile.o ide-pio-blacklist.o
# core IDE code
ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o
Index: b/drivers/ide/ide-ioctls.c
===================================================================
--- /dev/null
+++ b/drivers/ide/ide-ioctls.c
@@ -0,0 +1,289 @@
+/*
+ * IDE ioctls handling.
+ */
+
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+
+static const struct ide_ioctl_devset ide_ioctl_settings[] = {
+{ HDIO_GET_32BIT, HDIO_SET_32BIT, get_io_32bit, set_io_32bit },
+{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, get_ksettings, set_ksettings },
+{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, get_unmaskirq, set_unmaskirq },
+{ HDIO_GET_DMA, HDIO_SET_DMA, get_using_dma, set_using_dma },
+{ -1, HDIO_SET_PIO_MODE, NULL, set_pio_mode },
+{ 0 }
+};
+
+int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
+ unsigned int cmd, unsigned long arg,
+ const struct ide_ioctl_devset *s)
+{
+ unsigned long flags;
+ int err = -EOPNOTSUPP;
+
+ for (; s->get_ioctl; s++) {
+ if (s->get && s->get_ioctl == cmd)
+ goto read_val;
+ else if (s->set && s->set_ioctl == cmd)
+ goto set_val;
+ }
+
+ return err;
+
+read_val:
+ mutex_lock(&ide_setting_mtx);
+ spin_lock_irqsave(&ide_lock, flags);
+ err = s->get(drive);
+ spin_unlock_irqrestore(&ide_lock, flags);
+ mutex_unlock(&ide_setting_mtx);
+ return err >= 0 ? put_user(err, (long __user *)arg) : err;
+
+set_val:
+ if (bdev != bdev->bd_contains)
+ err = -EINVAL;
+ else {
+ if (!capable(CAP_SYS_ADMIN))
+ err = -EACCES;
+ else {
+ mutex_lock(&ide_setting_mtx);
+ err = s->set(drive, arg);
+ mutex_unlock(&ide_setting_mtx);
+ }
+ }
+ return err;
+}
+EXPORT_SYMBOL_GPL(ide_setting_ioctl);
+
+static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,
+ unsigned long arg)
+{
+ u16 *id = NULL;
+ int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142;
+ int rc = 0;
+
+ if (drive->id_read == 0) {
+ rc = -ENOMSG;
+ goto out;
+ }
+
+ id = kmalloc(size, GFP_KERNEL);
+ if (id == NULL) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(id, drive->id, size);
+ ata_id_to_hd_driveid(id);
+
+ if (copy_to_user((void __user *)arg, id, size))
+ rc = -EFAULT;
+
+ kfree(id);
+out:
+ return rc;
+}
+
+static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg)
+{
+ return put_user((drive->dsc_overlap << IDE_NICE_DSC_OVERLAP) |
+ (drive->nice1 << IDE_NICE_1), (long __user *)arg);
+}
+
+static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
+{
+ if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
+ return -EPERM;
+
+ if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&
+ (drive->media == ide_disk || drive->media == ide_floppy ||
+ drive->scsi))
+ return -EPERM;
+
+ drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
+ drive->nice1 = (arg >> IDE_NICE_1) & 1;
+
+ return 0;
+}
+
+static int ide_cmd_ioctl(ide_drive_t *drive, unsigned cmd, 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;
+
+ if (NULL == (void *) arg) {
+ struct request *rq;
+
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
+ err = blk_execute_rq(drive->queue, NULL, rq, 0);
+ blk_put_request(rq);
+
+ return err;
+ }
+
+ if (copy_from_user(args, (void __user *)arg, 4))
+ return -EFAULT;
+
+ memset(&tfargs, 0, sizeof(ide_task_t));
+ 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;
+ } else {
+ tf->nsect = args[1];
+ tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
+ IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
+ }
+ tf->command = args[0];
+ tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
+
+ if (args[3]) {
+ tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
+ bufsize = SECTOR_SIZE * args[3];
+ buf = kzalloc(bufsize, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+ }
+
+ 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);
+ goto abort;
+ }
+ }
+
+ err = ide_raw_taskfile(drive, &tfargs, 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;
+ if (buf) {
+ if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
+ err = -EFAULT;
+ kfree(buf);
+ }
+ return err;
+}
+
+static int ide_task_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg)
+{
+ void __user *p = (void __user *)arg;
+ int err = 0;
+ u8 args[7];
+ ide_task_t task;
+
+ 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;
+
+ err = ide_no_data_taskfile(drive, &task);
+
+ args[0] = task.tf.command;
+ memcpy(&args[1], &task.tf_array[7], 6);
+
+ if (copy_to_user(p, args, 7))
+ err = -EFAULT;
+
+ return err;
+}
+
+static int generic_drive_reset(ide_drive_t *drive)
+{
+ struct request *rq;
+ int ret = 0;
+
+ rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
+ 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);
+ return ret;
+}
+
+int generic_ide_ioctl(ide_drive_t *drive, struct file *file,
+ struct block_device *bdev,
+ unsigned int cmd, unsigned long arg)
+{
+ int err;
+
+ err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings);
+ if (err != -EOPNOTSUPP)
+ return err;
+
+ switch (cmd) {
+ case HDIO_OBSOLETE_IDENTITY:
+ case HDIO_GET_IDENTITY:
+ if (bdev != bdev->bd_contains)
+ return -EINVAL;
+ return ide_get_identity_ioctl(drive, cmd, arg);
+ case HDIO_GET_NICE:
+ return ide_get_nice_ioctl(drive, arg);
+ case HDIO_SET_NICE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ return ide_set_nice_ioctl(drive, arg);
+#ifdef CONFIG_IDE_TASK_IOCTL
+ case HDIO_DRIVE_TASKFILE:
+ if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ if (drive->media == ide_disk)
+ return ide_taskfile_ioctl(drive, cmd, arg);
+ return -ENOMSG;
+#endif
+ case HDIO_DRIVE_CMD:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ return ide_cmd_ioctl(drive, cmd, arg);
+ case HDIO_DRIVE_TASK:
+ if (!capable(CAP_SYS_RAWIO))
+ return -EACCES;
+ return ide_task_ioctl(drive, cmd, arg);
+ case HDIO_DRIVE_RESET:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ return generic_drive_reset(drive);
+ case HDIO_GET_BUSSTATE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ if (put_user(BUSSTATE_ON, (long __user *)arg))
+ return -EFAULT;
+ return 0;
+ case HDIO_SET_BUSSTATE:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+ return -EOPNOTSUPP;
+ default:
+ return -EINVAL;
+ }
+}
+EXPORT_SYMBOL(generic_ide_ioctl);
Index: b/drivers/ide/ide-taskfile.c
===================================================================
--- a/drivers/ide/ide-taskfile.c
+++ b/drivers/ide/ide-taskfile.c
@@ -726,112 +726,3 @@ abort:
return err;
}
#endif
-
-int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, 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;
-
- if (NULL == (void *) arg) {
- struct request *rq;
-
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
- rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
- err = blk_execute_rq(drive->queue, NULL, rq, 0);
- blk_put_request(rq);
-
- return err;
- }
-
- if (copy_from_user(args, (void __user *)arg, 4))
- return -EFAULT;
-
- memset(&tfargs, 0, sizeof(ide_task_t));
- 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;
- } else {
- tf->nsect = args[1];
- tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
- IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
- }
- tf->command = args[0];
- tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
-
- if (args[3]) {
- tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
- bufsize = SECTOR_SIZE * args[3];
- buf = kzalloc(bufsize, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
- }
-
- 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);
- goto abort;
- }
- }
-
- err = ide_raw_taskfile(drive, &tfargs, 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;
- if (buf) {
- if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
- err = -EFAULT;
- kfree(buf);
- }
- return err;
-}
-
-int ide_task_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg)
-{
- void __user *p = (void __user *)arg;
- int err = 0;
- u8 args[7];
- ide_task_t task;
-
- 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;
-
- err = ide_no_data_taskfile(drive, &task);
-
- args[0] = task.tf.command;
- memcpy(&args[1], &task.tf_array[7], 6);
-
- if (copy_to_user(p, args, 7))
- err = -EFAULT;
-
- return err;
-}
Index: b/drivers/ide/ide.c
===================================================================
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -489,180 +489,6 @@ static int generic_ide_resume(struct dev
return err;
}
-static int generic_drive_reset(ide_drive_t *drive)
-{
- struct request *rq;
- int ret = 0;
-
- rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
- 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);
- return ret;
-}
-
-static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,
- unsigned long arg)
-{
- u16 *id = NULL;
- int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142;
- int rc = 0;
-
- if (drive->id_read == 0) {
- rc = -ENOMSG;
- goto out;
- }
-
- id = kmalloc(size, GFP_KERNEL);
- if (id == NULL) {
- rc = -ENOMEM;
- goto out;
- }
-
- memcpy(id, drive->id, size);
- ata_id_to_hd_driveid(id);
-
- if (copy_to_user((void __user *)arg, id, size))
- rc = -EFAULT;
-
- kfree(id);
-out:
- return rc;
-}
-
-static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg)
-{
- return put_user((drive->dsc_overlap << IDE_NICE_DSC_OVERLAP) |
- (drive->nice1 << IDE_NICE_1), (long __user *)arg);
-}
-
-static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
-{
- if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
- return -EPERM;
-
- if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&
- (drive->media == ide_disk || drive->media == ide_floppy ||
- drive->scsi))
- return -EPERM;
-
- drive->dsc_overlap = (arg >> IDE_NICE_DSC_OVERLAP) & 1;
- drive->nice1 = (arg >> IDE_NICE_1) & 1;
-
- return 0;
-}
-
-static const struct ide_ioctl_devset ide_ioctl_settings[] = {
-{ HDIO_GET_32BIT, HDIO_SET_32BIT, get_io_32bit, set_io_32bit },
-{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, get_ksettings, set_ksettings },
-{ HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, get_unmaskirq, set_unmaskirq },
-{ HDIO_GET_DMA, HDIO_SET_DMA, get_using_dma, set_using_dma },
-{ -1, HDIO_SET_PIO_MODE, NULL, set_pio_mode },
-{ 0 }
-};
-
-int generic_ide_ioctl(ide_drive_t *drive, struct file *file,
- struct block_device *bdev,
- unsigned int cmd, unsigned long arg)
-{
- int err;
-
- err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings);
- if (err != -EOPNOTSUPP)
- return err;
-
- switch (cmd) {
- case HDIO_OBSOLETE_IDENTITY:
- case HDIO_GET_IDENTITY:
- if (bdev != bdev->bd_contains)
- return -EINVAL;
- return ide_get_identity_ioctl(drive, cmd, arg);
- case HDIO_GET_NICE:
- return ide_get_nice_ioctl(drive, arg);
- case HDIO_SET_NICE:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- return ide_set_nice_ioctl(drive, arg);
-#ifdef CONFIG_IDE_TASK_IOCTL
- case HDIO_DRIVE_TASKFILE:
- if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
- return -EACCES;
- if (drive->media == ide_disk)
- return ide_taskfile_ioctl(drive, cmd, arg);
- return -ENOMSG;
-#endif
- case HDIO_DRIVE_CMD:
- if (!capable(CAP_SYS_RAWIO))
- return -EACCES;
- return ide_cmd_ioctl(drive, cmd, arg);
- case HDIO_DRIVE_TASK:
- if (!capable(CAP_SYS_RAWIO))
- return -EACCES;
- return ide_task_ioctl(drive, cmd, arg);
- case HDIO_DRIVE_RESET:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- return generic_drive_reset(drive);
- case HDIO_GET_BUSSTATE:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- if (put_user(BUSSTATE_ON, (long __user *)arg))
- return -EFAULT;
- return 0;
- case HDIO_SET_BUSSTATE:
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- return -EOPNOTSUPP;
- default:
- return -EINVAL;
- }
-}
-EXPORT_SYMBOL(generic_ide_ioctl);
-
-int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
- unsigned int cmd, unsigned long arg,
- const struct ide_ioctl_devset *s)
-{
- unsigned long flags;
- int err = -EOPNOTSUPP;
-
- for (; s->get_ioctl; s++) {
- if (s->get && s->get_ioctl == cmd)
- goto read_val;
- else if (s->set && s->set_ioctl == cmd)
- goto set_val;
- }
-
- return err;
-
-read_val:
- mutex_lock(&ide_setting_mtx);
- spin_lock_irqsave(&ide_lock, flags);
- err = s->get(drive);
- spin_unlock_irqrestore(&ide_lock, flags);
- mutex_unlock(&ide_setting_mtx);
- return err >= 0 ? put_user(err, (long __user *)arg) : err;
-
-set_val:
- if (bdev != bdev->bd_contains)
- err = -EINVAL;
- else {
- if (!capable(CAP_SYS_ADMIN))
- err = -EACCES;
- else {
- mutex_lock(&ide_setting_mtx);
- err = s->set(drive, arg);
- mutex_unlock(&ide_setting_mtx);
- }
- }
- return err;
-}
-EXPORT_SYMBOL_GPL(ide_setting_ioctl);
-
/**
* ide_device_get - get an additional reference to a ide_drive_t
* @drive: device to get a reference to
Index: b/include/linux/ide.h
===================================================================
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1126,8 +1126,6 @@ int ide_raw_taskfile(ide_drive_t *, ide_
int ide_no_data_taskfile(ide_drive_t *, ide_task_t *);
int ide_taskfile_ioctl(ide_drive_t *, unsigned int, unsigned long);
-int ide_cmd_ioctl(ide_drive_t *, unsigned int, unsigned long);
-int ide_task_ioctl(ide_drive_t *, unsigned int, unsigned long);
extern int ide_driveid_update(ide_drive_t *);
extern int ide_config_drive_speed(ide_drive_t *, u8);
^ permalink raw reply [flat|nested] 4+ messages in thread