1 // SPDX-License-Identifier: GPL-2.0-only
6 #include <linux/compat.h>
7 #include <linux/export.h>
8 #include <linux/hdreg.h>
10 #include <linux/slab.h>
12 static int put_user_long(long val
, unsigned long arg
)
14 if (in_compat_syscall())
15 return put_user(val
, (compat_long_t __user
*)compat_ptr(arg
));
17 return put_user(val
, (long __user
*)arg
);
20 static const struct ide_ioctl_devset ide_ioctl_settings
[] = {
21 { HDIO_GET_32BIT
, HDIO_SET_32BIT
, &ide_devset_io_32bit
},
22 { HDIO_GET_KEEPSETTINGS
, HDIO_SET_KEEPSETTINGS
, &ide_devset_keepsettings
},
23 { HDIO_GET_UNMASKINTR
, HDIO_SET_UNMASKINTR
, &ide_devset_unmaskirq
},
24 { HDIO_GET_DMA
, HDIO_SET_DMA
, &ide_devset_using_dma
},
25 { -1, HDIO_SET_PIO_MODE
, &ide_devset_pio_mode
},
29 int ide_setting_ioctl(ide_drive_t
*drive
, struct block_device
*bdev
,
30 unsigned int cmd
, unsigned long arg
,
31 const struct ide_ioctl_devset
*s
)
33 const struct ide_devset
*ds
;
34 int err
= -EOPNOTSUPP
;
36 for (; (ds
= s
->setting
); s
++) {
37 if (ds
->get
&& s
->get_ioctl
== cmd
)
39 else if (ds
->set
&& s
->set_ioctl
== cmd
)
46 mutex_lock(&ide_setting_mtx
);
48 mutex_unlock(&ide_setting_mtx
);
49 return err
>= 0 ? put_user_long(err
, arg
) : err
;
52 if (bdev
!= bdev
->bd_contains
)
55 if (!capable(CAP_SYS_ADMIN
))
58 mutex_lock(&ide_setting_mtx
);
59 err
= ide_devset_execute(drive
, ds
, arg
);
60 mutex_unlock(&ide_setting_mtx
);
65 EXPORT_SYMBOL_GPL(ide_setting_ioctl
);
67 static int ide_get_identity_ioctl(ide_drive_t
*drive
, unsigned int cmd
,
71 int size
= (cmd
== HDIO_GET_IDENTITY
) ? (ATA_ID_WORDS
* 2) : 142;
74 if ((drive
->dev_flags
& IDE_DFLAG_ID_READ
) == 0) {
79 /* ata_id_to_hd_driveid() relies on 'id' to be fully allocated. */
80 id
= kmalloc(ATA_ID_WORDS
* 2, GFP_KERNEL
);
86 memcpy(id
, drive
->id
, size
);
87 ata_id_to_hd_driveid(id
);
89 if (copy_to_user(argp
, id
, size
))
97 static int ide_get_nice_ioctl(ide_drive_t
*drive
, unsigned long arg
)
99 return put_user_long((!!(drive
->dev_flags
& IDE_DFLAG_DSC_OVERLAP
)
100 << IDE_NICE_DSC_OVERLAP
) |
101 (!!(drive
->dev_flags
& IDE_DFLAG_NICE1
)
102 << IDE_NICE_1
), arg
);
105 static int ide_set_nice_ioctl(ide_drive_t
*drive
, unsigned long arg
)
107 if (arg
!= (arg
& ((1 << IDE_NICE_DSC_OVERLAP
) | (1 << IDE_NICE_1
))))
110 if (((arg
>> IDE_NICE_DSC_OVERLAP
) & 1) &&
111 (drive
->media
!= ide_tape
))
114 if ((arg
>> IDE_NICE_DSC_OVERLAP
) & 1)
115 drive
->dev_flags
|= IDE_DFLAG_DSC_OVERLAP
;
117 drive
->dev_flags
&= ~IDE_DFLAG_DSC_OVERLAP
;
119 if ((arg
>> IDE_NICE_1
) & 1)
120 drive
->dev_flags
|= IDE_DFLAG_NICE1
;
122 drive
->dev_flags
&= ~IDE_DFLAG_NICE1
;
127 static int ide_cmd_ioctl(ide_drive_t
*drive
, void __user
*argp
)
130 int bufsize
= 0, err
= 0;
131 u8 args
[4], xfer_rate
= 0;
133 struct ide_taskfile
*tf
= &cmd
.tf
;
138 rq
= blk_get_request(drive
->queue
, REQ_OP_DRV_IN
, 0);
139 ide_req(rq
)->type
= ATA_PRIV_TASKFILE
;
140 blk_execute_rq(drive
->queue
, NULL
, rq
, 0);
141 err
= scsi_req(rq
)->result
? -EIO
: 0;
147 if (copy_from_user(args
, argp
, 4))
150 memset(&cmd
, 0, sizeof(cmd
));
151 tf
->feature
= args
[2];
152 if (args
[0] == ATA_CMD_SMART
) {
155 tf
->lbam
= ATA_SMART_LBAM_PASS
;
156 tf
->lbah
= ATA_SMART_LBAH_PASS
;
157 cmd
.valid
.out
.tf
= IDE_VALID_OUT_TF
;
158 cmd
.valid
.in
.tf
= IDE_VALID_NSECT
;
161 cmd
.valid
.out
.tf
= IDE_VALID_FEATURE
| IDE_VALID_NSECT
;
162 cmd
.valid
.in
.tf
= IDE_VALID_NSECT
;
164 tf
->command
= args
[0];
165 cmd
.protocol
= args
[3] ? ATA_PROT_PIO
: ATA_PROT_NODATA
;
168 cmd
.tf_flags
|= IDE_TFLAG_IO_16BIT
;
169 bufsize
= SECTOR_SIZE
* args
[3];
170 buf
= kzalloc(bufsize
, GFP_KERNEL
);
175 if (tf
->command
== ATA_CMD_SET_FEATURES
&&
176 tf
->feature
== SETFEATURES_XFER
&&
177 tf
->nsect
>= XFER_SW_DMA_0
) {
178 xfer_rate
= ide_find_dma_mode(drive
, tf
->nsect
);
179 if (xfer_rate
!= tf
->nsect
) {
184 cmd
.tf_flags
|= IDE_TFLAG_SET_XFER
;
187 err
= ide_raw_taskfile(drive
, &cmd
, buf
, args
[3]);
189 args
[0] = tf
->status
;
193 if (copy_to_user(argp
, &args
, 4))
196 if (copy_to_user((argp
+ 4), buf
, bufsize
))
203 static int ide_task_ioctl(ide_drive_t
*drive
, void __user
*p
)
209 if (copy_from_user(args
, p
, 7))
212 memset(&cmd
, 0, sizeof(cmd
));
213 memcpy(&cmd
.tf
.feature
, &args
[1], 6);
214 cmd
.tf
.command
= args
[0];
215 cmd
.valid
.out
.tf
= IDE_VALID_OUT_TF
| IDE_VALID_DEVICE
;
216 cmd
.valid
.in
.tf
= IDE_VALID_IN_TF
| IDE_VALID_DEVICE
;
218 err
= ide_no_data_taskfile(drive
, &cmd
);
220 args
[0] = cmd
.tf
.command
;
221 memcpy(&args
[1], &cmd
.tf
.feature
, 6);
223 if (copy_to_user(p
, args
, 7))
229 static int generic_drive_reset(ide_drive_t
*drive
)
234 rq
= blk_get_request(drive
->queue
, REQ_OP_DRV_IN
, 0);
235 ide_req(rq
)->type
= ATA_PRIV_MISC
;
236 scsi_req(rq
)->cmd_len
= 1;
237 scsi_req(rq
)->cmd
[0] = REQ_DRIVE_RESET
;
238 blk_execute_rq(drive
->queue
, NULL
, rq
, 1);
239 ret
= scsi_req(rq
)->result
;
244 int generic_ide_ioctl(ide_drive_t
*drive
, struct block_device
*bdev
,
245 unsigned int cmd
, unsigned long arg
)
248 void __user
*argp
= (void __user
*)arg
;
250 if (in_compat_syscall())
251 argp
= compat_ptr(arg
);
253 err
= ide_setting_ioctl(drive
, bdev
, cmd
, arg
, ide_ioctl_settings
);
254 if (err
!= -EOPNOTSUPP
)
258 case HDIO_OBSOLETE_IDENTITY
:
259 case HDIO_GET_IDENTITY
:
260 if (bdev
!= bdev
->bd_contains
)
262 return ide_get_identity_ioctl(drive
, cmd
, argp
);
264 return ide_get_nice_ioctl(drive
, arg
);
266 if (!capable(CAP_SYS_ADMIN
))
268 return ide_set_nice_ioctl(drive
, arg
);
269 #ifdef CONFIG_IDE_TASK_IOCTL
270 case HDIO_DRIVE_TASKFILE
:
271 if (!capable(CAP_SYS_ADMIN
) || !capable(CAP_SYS_RAWIO
))
273 /* missing compat handler for HDIO_DRIVE_TASKFILE */
274 if (in_compat_syscall())
276 if (drive
->media
== ide_disk
)
277 return ide_taskfile_ioctl(drive
, arg
);
281 if (!capable(CAP_SYS_RAWIO
))
283 return ide_cmd_ioctl(drive
, argp
);
284 case HDIO_DRIVE_TASK
:
285 if (!capable(CAP_SYS_RAWIO
))
287 return ide_task_ioctl(drive
, argp
);
288 case HDIO_DRIVE_RESET
:
289 if (!capable(CAP_SYS_ADMIN
))
291 return generic_drive_reset(drive
);
292 case HDIO_GET_BUSSTATE
:
293 if (!capable(CAP_SYS_ADMIN
))
295 if (put_user_long(BUSSTATE_ON
, arg
))
298 case HDIO_SET_BUSSTATE
:
299 if (!capable(CAP_SYS_ADMIN
))
306 EXPORT_SYMBOL(generic_ide_ioctl
);