ide-ioctls.c revision 97100fc816badbbc162644cfde7ad39ae9211fb4
1/*
2 * IDE ioctls handling.
3 */
4
5#include <linux/hdreg.h>
6#include <linux/ide.h>
7
8static const struct ide_ioctl_devset ide_ioctl_settings[] = {
9{ HDIO_GET_32BIT,	 HDIO_SET_32BIT,	&ide_devset_io_32bit  },
10{ HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS,	&ide_devset_keepsettings },
11{ HDIO_GET_UNMASKINTR,	 HDIO_SET_UNMASKINTR,	&ide_devset_unmaskirq },
12{ HDIO_GET_DMA,		 HDIO_SET_DMA,		&ide_devset_using_dma },
13{ -1,			 HDIO_SET_PIO_MODE,	&ide_devset_pio_mode  },
14{ 0 }
15};
16
17int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
18		      unsigned int cmd, unsigned long arg,
19		      const struct ide_ioctl_devset *s)
20{
21	const struct ide_devset *ds;
22	unsigned long flags;
23	int err = -EOPNOTSUPP;
24
25	for (; (ds = s->setting); s++) {
26		if (ds->get && s->get_ioctl == cmd)
27			goto read_val;
28		else if (ds->set && s->set_ioctl == cmd)
29			goto set_val;
30	}
31
32	return err;
33
34read_val:
35	mutex_lock(&ide_setting_mtx);
36	spin_lock_irqsave(&ide_lock, flags);
37	err = ds->get(drive);
38	spin_unlock_irqrestore(&ide_lock, flags);
39	mutex_unlock(&ide_setting_mtx);
40	return err >= 0 ? put_user(err, (long __user *)arg) : err;
41
42set_val:
43	if (bdev != bdev->bd_contains)
44		err = -EINVAL;
45	else {
46		if (!capable(CAP_SYS_ADMIN))
47			err = -EACCES;
48		else {
49			mutex_lock(&ide_setting_mtx);
50			err = ide_devset_execute(drive, ds, arg);
51			mutex_unlock(&ide_setting_mtx);
52		}
53	}
54	return err;
55}
56EXPORT_SYMBOL_GPL(ide_setting_ioctl);
57
58static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,
59				  unsigned long arg)
60{
61	u16 *id = NULL;
62	int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142;
63	int rc = 0;
64
65	if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
66		rc = -ENOMSG;
67		goto out;
68	}
69
70	id = kmalloc(size, GFP_KERNEL);
71	if (id == NULL) {
72		rc = -ENOMEM;
73		goto out;
74	}
75
76	memcpy(id, drive->id, size);
77	ata_id_to_hd_driveid(id);
78
79	if (copy_to_user((void __user *)arg, id, size))
80		rc = -EFAULT;
81
82	kfree(id);
83out:
84	return rc;
85}
86
87static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg)
88{
89	return put_user((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)
90			 << IDE_NICE_DSC_OVERLAP) |
91			(!!(drive->dev_flags & IDE_DFLAG_NICE1)
92			 << IDE_NICE_1), (long __user *)arg);
93}
94
95static int ide_set_nice_ioctl(ide_drive_t *drive, unsigned long arg)
96{
97	if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP) | (1 << IDE_NICE_1))))
98		return -EPERM;
99
100	if (((arg >> IDE_NICE_DSC_OVERLAP) & 1) &&
101	    (drive->media == ide_disk || drive->media == ide_floppy ||
102	     (drive->dev_flags & IDE_DFLAG_SCSI)))
103		return -EPERM;
104
105	if ((arg >> IDE_NICE_DSC_OVERLAP) & 1)
106		drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP;
107	else
108		drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
109
110	if ((arg >> IDE_NICE_1) & 1)
111		drive->dev_flags |= IDE_DFLAG_NICE1;
112	else
113		drive->dev_flags &= ~IDE_DFLAG_NICE1;
114
115	return 0;
116}
117
118static int ide_cmd_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg)
119{
120	u8 *buf = NULL;
121	int bufsize = 0, err = 0;
122	u8 args[4], xfer_rate = 0;
123	ide_task_t tfargs;
124	struct ide_taskfile *tf = &tfargs.tf;
125	u16 *id = drive->id;
126
127	if (NULL == (void *) arg) {
128		struct request *rq;
129
130		rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
131		rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
132		err = blk_execute_rq(drive->queue, NULL, rq, 0);
133		blk_put_request(rq);
134
135		return err;
136	}
137
138	if (copy_from_user(args, (void __user *)arg, 4))
139		return -EFAULT;
140
141	memset(&tfargs, 0, sizeof(ide_task_t));
142	tf->feature = args[2];
143	if (args[0] == ATA_CMD_SMART) {
144		tf->nsect = args[3];
145		tf->lbal  = args[1];
146		tf->lbam  = 0x4f;
147		tf->lbah  = 0xc2;
148		tfargs.tf_flags = IDE_TFLAG_OUT_TF | IDE_TFLAG_IN_NSECT;
149	} else {
150		tf->nsect = args[1];
151		tfargs.tf_flags = IDE_TFLAG_OUT_FEATURE |
152				  IDE_TFLAG_OUT_NSECT | IDE_TFLAG_IN_NSECT;
153	}
154	tf->command = args[0];
155	tfargs.data_phase = args[3] ? TASKFILE_IN : TASKFILE_NO_DATA;
156
157	if (args[3]) {
158		tfargs.tf_flags |= IDE_TFLAG_IO_16BIT;
159		bufsize = SECTOR_SIZE * args[3];
160		buf = kzalloc(bufsize, GFP_KERNEL);
161		if (buf == NULL)
162			return -ENOMEM;
163	}
164
165	if (tf->command == ATA_CMD_SET_FEATURES &&
166	    tf->feature == SETFEATURES_XFER &&
167	    tf->nsect >= XFER_SW_DMA_0 &&
168	    (id[ATA_ID_UDMA_MODES] ||
169	     id[ATA_ID_MWDMA_MODES] ||
170	     id[ATA_ID_SWDMA_MODES])) {
171		xfer_rate = args[1];
172		if (tf->nsect > XFER_UDMA_2 && !eighty_ninty_three(drive)) {
173			printk(KERN_WARNING "%s: UDMA speeds >UDMA33 cannot "
174					    "be set\n", drive->name);
175			goto abort;
176		}
177	}
178
179	err = ide_raw_taskfile(drive, &tfargs, buf, args[3]);
180
181	args[0] = tf->status;
182	args[1] = tf->error;
183	args[2] = tf->nsect;
184
185	if (!err && xfer_rate) {
186		/* active-retuning-calls future */
187		ide_set_xfer_rate(drive, xfer_rate);
188		ide_driveid_update(drive);
189	}
190abort:
191	if (copy_to_user((void __user *)arg, &args, 4))
192		err = -EFAULT;
193	if (buf) {
194		if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
195			err = -EFAULT;
196		kfree(buf);
197	}
198	return err;
199}
200
201static int ide_task_ioctl(ide_drive_t *drive, unsigned cmd, unsigned long arg)
202{
203	void __user *p = (void __user *)arg;
204	int err = 0;
205	u8 args[7];
206	ide_task_t task;
207
208	if (copy_from_user(args, p, 7))
209		return -EFAULT;
210
211	memset(&task, 0, sizeof(task));
212	memcpy(&task.tf_array[7], &args[1], 6);
213	task.tf.command = args[0];
214	task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE;
215
216	err = ide_no_data_taskfile(drive, &task);
217
218	args[0] = task.tf.command;
219	memcpy(&args[1], &task.tf_array[7], 6);
220
221	if (copy_to_user(p, args, 7))
222		err = -EFAULT;
223
224	return err;
225}
226
227static int generic_drive_reset(ide_drive_t *drive)
228{
229	struct request *rq;
230	int ret = 0;
231
232	rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
233	rq->cmd_type = REQ_TYPE_SPECIAL;
234	rq->cmd_len = 1;
235	rq->cmd[0] = REQ_DRIVE_RESET;
236	rq->cmd_flags |= REQ_SOFTBARRIER;
237	if (blk_execute_rq(drive->queue, NULL, rq, 1))
238		ret = rq->errors;
239	blk_put_request(rq);
240	return ret;
241}
242
243int generic_ide_ioctl(ide_drive_t *drive, struct file *file,
244		      struct block_device *bdev,
245		      unsigned int cmd, unsigned long arg)
246{
247	int err;
248
249	err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings);
250	if (err != -EOPNOTSUPP)
251		return err;
252
253	switch (cmd) {
254	case HDIO_OBSOLETE_IDENTITY:
255	case HDIO_GET_IDENTITY:
256		if (bdev != bdev->bd_contains)
257			return -EINVAL;
258		return ide_get_identity_ioctl(drive, cmd, arg);
259	case HDIO_GET_NICE:
260		return ide_get_nice_ioctl(drive, arg);
261	case HDIO_SET_NICE:
262		if (!capable(CAP_SYS_ADMIN))
263			return -EACCES;
264		return ide_set_nice_ioctl(drive, arg);
265#ifdef CONFIG_IDE_TASK_IOCTL
266	case HDIO_DRIVE_TASKFILE:
267		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SYS_RAWIO))
268			return -EACCES;
269		if (drive->media == ide_disk)
270			return ide_taskfile_ioctl(drive, cmd, arg);
271		return -ENOMSG;
272#endif
273	case HDIO_DRIVE_CMD:
274		if (!capable(CAP_SYS_RAWIO))
275			return -EACCES;
276		return ide_cmd_ioctl(drive, cmd, arg);
277	case HDIO_DRIVE_TASK:
278		if (!capable(CAP_SYS_RAWIO))
279			return -EACCES;
280		return ide_task_ioctl(drive, cmd, arg);
281	case HDIO_DRIVE_RESET:
282		if (!capable(CAP_SYS_ADMIN))
283			return -EACCES;
284		return generic_drive_reset(drive);
285	case HDIO_GET_BUSSTATE:
286		if (!capable(CAP_SYS_ADMIN))
287			return -EACCES;
288		if (put_user(BUSSTATE_ON, (long __user *)arg))
289			return -EFAULT;
290		return 0;
291	case HDIO_SET_BUSSTATE:
292		if (!capable(CAP_SYS_ADMIN))
293			return -EACCES;
294		return -EOPNOTSUPP;
295	default:
296		return -EINVAL;
297	}
298}
299EXPORT_SYMBOL(generic_ide_ioctl);
300