Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ide-ioctls.c
Go to the documentation of this file.
1 /*
2  * IDE ioctls handling.
3  */
4 
5 #include <linux/export.h>
6 #include <linux/hdreg.h>
7 #include <linux/ide.h>
8 #include <linux/slab.h>
9 
10 static const struct ide_ioctl_devset ide_ioctl_settings[] = {
11 { HDIO_GET_32BIT, HDIO_SET_32BIT, &ide_devset_io_32bit },
12 { HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, &ide_devset_keepsettings },
13 { HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, &ide_devset_unmaskirq },
14 { HDIO_GET_DMA, HDIO_SET_DMA, &ide_devset_using_dma },
15 { -1, HDIO_SET_PIO_MODE, &ide_devset_pio_mode },
16 { 0 }
17 };
18 
19 int ide_setting_ioctl(ide_drive_t *drive, struct block_device *bdev,
20  unsigned int cmd, unsigned long arg,
21  const struct ide_ioctl_devset *s)
22 {
23  const struct ide_devset *ds;
24  int err = -EOPNOTSUPP;
25 
26  for (; (ds = s->setting); s++) {
27  if (ds->get && s->get_ioctl == cmd)
28  goto read_val;
29  else if (ds->set && s->set_ioctl == cmd)
30  goto set_val;
31  }
32 
33  return err;
34 
35 read_val:
37  err = ds->get(drive);
39  return err >= 0 ? put_user(err, (long __user *)arg) : err;
40 
41 set_val:
42  if (bdev != bdev->bd_contains)
43  err = -EINVAL;
44  else {
45  if (!capable(CAP_SYS_ADMIN))
46  err = -EACCES;
47  else {
49  err = ide_devset_execute(drive, ds, arg);
51  }
52  }
53  return err;
54 }
56 
57 static int ide_get_identity_ioctl(ide_drive_t *drive, unsigned int cmd,
58  unsigned long arg)
59 {
60  u16 *id = NULL;
61  int size = (cmd == HDIO_GET_IDENTITY) ? (ATA_ID_WORDS * 2) : 142;
62  int rc = 0;
63 
64  if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) {
65  rc = -ENOMSG;
66  goto out;
67  }
68 
69  /* ata_id_to_hd_driveid() relies on 'id' to be fully allocated. */
70  id = kmalloc(ATA_ID_WORDS * 2, 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);
83 out:
84  return rc;
85 }
86 
87 static int ide_get_nice_ioctl(ide_drive_t *drive, unsigned long arg)
88 {
89  return put_user((!!(drive->dev_flags & IDE_DFLAG_DSC_OVERLAP)
91  (!!(drive->dev_flags & IDE_DFLAG_NICE1)
92  << IDE_NICE_1), (long __user *)arg);
93 }
94 
95 static 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_tape))
102  return -EPERM;
103 
104  if ((arg >> IDE_NICE_DSC_OVERLAP) & 1)
106  else
107  drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP;
108 
109  if ((arg >> IDE_NICE_1) & 1)
110  drive->dev_flags |= IDE_DFLAG_NICE1;
111  else
112  drive->dev_flags &= ~IDE_DFLAG_NICE1;
113 
114  return 0;
115 }
116 
117 static int ide_cmd_ioctl(ide_drive_t *drive, unsigned long arg)
118 {
119  u8 *buf = NULL;
120  int bufsize = 0, err = 0;
121  u8 args[4], xfer_rate = 0;
122  struct ide_cmd cmd;
123  struct ide_taskfile *tf = &cmd.tf;
124 
125  if (NULL == (void *) arg) {
126  struct request *rq;
127 
128  rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
129  rq->cmd_type = REQ_TYPE_ATA_TASKFILE;
130  err = blk_execute_rq(drive->queue, NULL, rq, 0);
131  blk_put_request(rq);
132 
133  return err;
134  }
135 
136  if (copy_from_user(args, (void __user *)arg, 4))
137  return -EFAULT;
138 
139  memset(&cmd, 0, sizeof(cmd));
140  tf->feature = args[2];
141  if (args[0] == ATA_CMD_SMART) {
142  tf->nsect = args[3];
143  tf->lbal = args[1];
144  tf->lbam = 0x4f;
145  tf->lbah = 0xc2;
146  cmd.valid.out.tf = IDE_VALID_OUT_TF;
147  cmd.valid.in.tf = IDE_VALID_NSECT;
148  } else {
149  tf->nsect = args[1];
150  cmd.valid.out.tf = IDE_VALID_FEATURE | IDE_VALID_NSECT;
151  cmd.valid.in.tf = IDE_VALID_NSECT;
152  }
153  tf->command = args[0];
154  cmd.protocol = args[3] ? ATA_PROT_PIO : ATA_PROT_NODATA;
155 
156  if (args[3]) {
157  cmd.tf_flags |= IDE_TFLAG_IO_16BIT;
158  bufsize = SECTOR_SIZE * args[3];
159  buf = kzalloc(bufsize, GFP_KERNEL);
160  if (buf == NULL)
161  return -ENOMEM;
162  }
163 
164  if (tf->command == ATA_CMD_SET_FEATURES &&
165  tf->feature == SETFEATURES_XFER &&
166  tf->nsect >= XFER_SW_DMA_0) {
167  xfer_rate = ide_find_dma_mode(drive, tf->nsect);
168  if (xfer_rate != tf->nsect) {
169  err = -EINVAL;
170  goto abort;
171  }
172 
173  cmd.tf_flags |= IDE_TFLAG_SET_XFER;
174  }
175 
176  err = ide_raw_taskfile(drive, &cmd, buf, args[3]);
177 
178  args[0] = tf->status;
179  args[1] = tf->error;
180  args[2] = tf->nsect;
181 abort:
182  if (copy_to_user((void __user *)arg, &args, 4))
183  err = -EFAULT;
184  if (buf) {
185  if (copy_to_user((void __user *)(arg + 4), buf, bufsize))
186  err = -EFAULT;
187  kfree(buf);
188  }
189  return err;
190 }
191 
192 static int ide_task_ioctl(ide_drive_t *drive, unsigned long arg)
193 {
194  void __user *p = (void __user *)arg;
195  int err = 0;
196  u8 args[7];
197  struct ide_cmd cmd;
198 
199  if (copy_from_user(args, p, 7))
200  return -EFAULT;
201 
202  memset(&cmd, 0, sizeof(cmd));
203  memcpy(&cmd.tf.feature, &args[1], 6);
204  cmd.tf.command = args[0];
205  cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE;
206  cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE;
207 
208  err = ide_no_data_taskfile(drive, &cmd);
209 
210  args[0] = cmd.tf.command;
211  memcpy(&args[1], &cmd.tf.feature, 6);
212 
213  if (copy_to_user(p, args, 7))
214  err = -EFAULT;
215 
216  return err;
217 }
218 
219 static int generic_drive_reset(ide_drive_t *drive)
220 {
221  struct request *rq;
222  int ret = 0;
223 
224  rq = blk_get_request(drive->queue, READ, __GFP_WAIT);
225  rq->cmd_type = REQ_TYPE_SPECIAL;
226  rq->cmd_len = 1;
227  rq->cmd[0] = REQ_DRIVE_RESET;
228  if (blk_execute_rq(drive->queue, NULL, rq, 1))
229  ret = rq->errors;
230  blk_put_request(rq);
231  return ret;
232 }
233 
234 int generic_ide_ioctl(ide_drive_t *drive, struct block_device *bdev,
235  unsigned int cmd, unsigned long arg)
236 {
237  int err;
238 
239  err = ide_setting_ioctl(drive, bdev, cmd, arg, ide_ioctl_settings);
240  if (err != -EOPNOTSUPP)
241  return err;
242 
243  switch (cmd) {
245  case HDIO_GET_IDENTITY:
246  if (bdev != bdev->bd_contains)
247  return -EINVAL;
248  return ide_get_identity_ioctl(drive, cmd, arg);
249  case HDIO_GET_NICE:
250  return ide_get_nice_ioctl(drive, arg);
251  case HDIO_SET_NICE:
252  if (!capable(CAP_SYS_ADMIN))
253  return -EACCES;
254  return ide_set_nice_ioctl(drive, arg);
255 #ifdef CONFIG_IDE_TASK_IOCTL
256  case HDIO_DRIVE_TASKFILE:
258  return -EACCES;
259  if (drive->media == ide_disk)
260  return ide_taskfile_ioctl(drive, arg);
261  return -ENOMSG;
262 #endif
263  case HDIO_DRIVE_CMD:
264  if (!capable(CAP_SYS_RAWIO))
265  return -EACCES;
266  return ide_cmd_ioctl(drive, arg);
267  case HDIO_DRIVE_TASK:
268  if (!capable(CAP_SYS_RAWIO))
269  return -EACCES;
270  return ide_task_ioctl(drive, arg);
271  case HDIO_DRIVE_RESET:
272  if (!capable(CAP_SYS_ADMIN))
273  return -EACCES;
274  return generic_drive_reset(drive);
275  case HDIO_GET_BUSSTATE:
276  if (!capable(CAP_SYS_ADMIN))
277  return -EACCES;
278  if (put_user(BUSSTATE_ON, (long __user *)arg))
279  return -EFAULT;
280  return 0;
281  case HDIO_SET_BUSSTATE:
282  if (!capable(CAP_SYS_ADMIN))
283  return -EACCES;
284  return -EOPNOTSUPP;
285  default:
286  return -EINVAL;
287  }
288 }