diff options
author | Arnd Bergmann <arnd@arndb.de> | 2007-10-09 07:23:57 -0400 |
---|---|---|
committer | Jens Axboe <axboe@carl.home.kernel.dk> | 2007-10-10 03:26:00 -0400 |
commit | 1ca91cd0336b05b91c51b403c9ed9d297813533f (patch) | |
tree | ae4e2fee28886f3330680921ad088294d97ddb31 /block | |
parent | b3087cc4f31a66c8c7b63419e913ed9d34145f10 (diff) |
compat_ioctl: move floppy handlers to block/compat_ioctl.c
The floppy ioctls are used by multiple drivers, so they should be
handled in a shared location. Also, add minor cleanups.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/compat_ioctl.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 92b3e8d07ca6..f84093b97f70 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c | |||
@@ -203,6 +203,332 @@ static int compat_blkpg_ioctl(struct inode *inode, struct file *file, | |||
203 | #define BLKBSZSET_32 _IOW(0x12, 113, int) | 203 | #define BLKBSZSET_32 _IOW(0x12, 113, int) |
204 | #define BLKGETSIZE64_32 _IOR(0x12, 114, int) | 204 | #define BLKGETSIZE64_32 _IOR(0x12, 114, int) |
205 | 205 | ||
206 | struct compat_floppy_struct { | ||
207 | compat_uint_t size; | ||
208 | compat_uint_t sect; | ||
209 | compat_uint_t head; | ||
210 | compat_uint_t track; | ||
211 | compat_uint_t stretch; | ||
212 | unsigned char gap; | ||
213 | unsigned char rate; | ||
214 | unsigned char spec1; | ||
215 | unsigned char fmt_gap; | ||
216 | const compat_caddr_t name; | ||
217 | }; | ||
218 | |||
219 | struct compat_floppy_drive_params { | ||
220 | char cmos; | ||
221 | compat_ulong_t max_dtr; | ||
222 | compat_ulong_t hlt; | ||
223 | compat_ulong_t hut; | ||
224 | compat_ulong_t srt; | ||
225 | compat_ulong_t spinup; | ||
226 | compat_ulong_t spindown; | ||
227 | unsigned char spindown_offset; | ||
228 | unsigned char select_delay; | ||
229 | unsigned char rps; | ||
230 | unsigned char tracks; | ||
231 | compat_ulong_t timeout; | ||
232 | unsigned char interleave_sect; | ||
233 | struct floppy_max_errors max_errors; | ||
234 | char flags; | ||
235 | char read_track; | ||
236 | short autodetect[8]; | ||
237 | compat_int_t checkfreq; | ||
238 | compat_int_t native_format; | ||
239 | }; | ||
240 | |||
241 | struct compat_floppy_drive_struct { | ||
242 | signed char flags; | ||
243 | compat_ulong_t spinup_date; | ||
244 | compat_ulong_t select_date; | ||
245 | compat_ulong_t first_read_date; | ||
246 | short probed_format; | ||
247 | short track; | ||
248 | short maxblock; | ||
249 | short maxtrack; | ||
250 | compat_int_t generation; | ||
251 | compat_int_t keep_data; | ||
252 | compat_int_t fd_ref; | ||
253 | compat_int_t fd_device; | ||
254 | compat_int_t last_checked; | ||
255 | compat_caddr_t dmabuf; | ||
256 | compat_int_t bufblocks; | ||
257 | }; | ||
258 | |||
259 | struct compat_floppy_fdc_state { | ||
260 | compat_int_t spec1; | ||
261 | compat_int_t spec2; | ||
262 | compat_int_t dtr; | ||
263 | unsigned char version; | ||
264 | unsigned char dor; | ||
265 | compat_ulong_t address; | ||
266 | unsigned int rawcmd:2; | ||
267 | unsigned int reset:1; | ||
268 | unsigned int need_configure:1; | ||
269 | unsigned int perp_mode:2; | ||
270 | unsigned int has_fifo:1; | ||
271 | unsigned int driver_version; | ||
272 | unsigned char track[4]; | ||
273 | }; | ||
274 | |||
275 | struct compat_floppy_write_errors { | ||
276 | unsigned int write_errors; | ||
277 | compat_ulong_t first_error_sector; | ||
278 | compat_int_t first_error_generation; | ||
279 | compat_ulong_t last_error_sector; | ||
280 | compat_int_t last_error_generation; | ||
281 | compat_uint_t badness; | ||
282 | }; | ||
283 | |||
284 | #define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) | ||
285 | #define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct) | ||
286 | #define FDGETPRM32 _IOR(2, 0x04, struct compat_floppy_struct) | ||
287 | #define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params) | ||
288 | #define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params) | ||
289 | #define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct) | ||
290 | #define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct) | ||
291 | #define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) | ||
292 | #define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) | ||
293 | |||
294 | static struct { | ||
295 | unsigned int cmd32; | ||
296 | unsigned int cmd; | ||
297 | } fd_ioctl_trans_table[] = { | ||
298 | { FDSETPRM32, FDSETPRM }, | ||
299 | { FDDEFPRM32, FDDEFPRM }, | ||
300 | { FDGETPRM32, FDGETPRM }, | ||
301 | { FDSETDRVPRM32, FDSETDRVPRM }, | ||
302 | { FDGETDRVPRM32, FDGETDRVPRM }, | ||
303 | { FDGETDRVSTAT32, FDGETDRVSTAT }, | ||
304 | { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, | ||
305 | { FDGETFDCSTAT32, FDGETFDCSTAT }, | ||
306 | { FDWERRORGET32, FDWERRORGET } | ||
307 | }; | ||
308 | |||
309 | #define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) | ||
310 | |||
311 | static int compat_fd_ioctl(struct inode *inode, struct file *file, | ||
312 | struct gendisk *disk, unsigned int cmd, unsigned long arg) | ||
313 | { | ||
314 | mm_segment_t old_fs = get_fs(); | ||
315 | void *karg = NULL; | ||
316 | unsigned int kcmd = 0; | ||
317 | int i, err; | ||
318 | |||
319 | for (i = 0; i < NR_FD_IOCTL_TRANS; i++) | ||
320 | if (cmd == fd_ioctl_trans_table[i].cmd32) { | ||
321 | kcmd = fd_ioctl_trans_table[i].cmd; | ||
322 | break; | ||
323 | } | ||
324 | if (!kcmd) | ||
325 | return -EINVAL; | ||
326 | |||
327 | switch (cmd) { | ||
328 | case FDSETPRM32: | ||
329 | case FDDEFPRM32: | ||
330 | case FDGETPRM32: | ||
331 | { | ||
332 | compat_uptr_t name; | ||
333 | struct compat_floppy_struct __user *uf; | ||
334 | struct floppy_struct *f; | ||
335 | |||
336 | uf = compat_ptr(arg); | ||
337 | f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); | ||
338 | if (!karg) | ||
339 | return -ENOMEM; | ||
340 | if (cmd == FDGETPRM32) | ||
341 | break; | ||
342 | err = __get_user(f->size, &uf->size); | ||
343 | err |= __get_user(f->sect, &uf->sect); | ||
344 | err |= __get_user(f->head, &uf->head); | ||
345 | err |= __get_user(f->track, &uf->track); | ||
346 | err |= __get_user(f->stretch, &uf->stretch); | ||
347 | err |= __get_user(f->gap, &uf->gap); | ||
348 | err |= __get_user(f->rate, &uf->rate); | ||
349 | err |= __get_user(f->spec1, &uf->spec1); | ||
350 | err |= __get_user(f->fmt_gap, &uf->fmt_gap); | ||
351 | err |= __get_user(name, &uf->name); | ||
352 | f->name = compat_ptr(name); | ||
353 | if (err) { | ||
354 | err = -EFAULT; | ||
355 | goto out; | ||
356 | } | ||
357 | break; | ||
358 | } | ||
359 | case FDSETDRVPRM32: | ||
360 | case FDGETDRVPRM32: | ||
361 | { | ||
362 | struct compat_floppy_drive_params __user *uf; | ||
363 | struct floppy_drive_params *f; | ||
364 | |||
365 | uf = compat_ptr(arg); | ||
366 | f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); | ||
367 | if (!karg) | ||
368 | return -ENOMEM; | ||
369 | if (cmd == FDGETDRVPRM32) | ||
370 | break; | ||
371 | err = __get_user(f->cmos, &uf->cmos); | ||
372 | err |= __get_user(f->max_dtr, &uf->max_dtr); | ||
373 | err |= __get_user(f->hlt, &uf->hlt); | ||
374 | err |= __get_user(f->hut, &uf->hut); | ||
375 | err |= __get_user(f->srt, &uf->srt); | ||
376 | err |= __get_user(f->spinup, &uf->spinup); | ||
377 | err |= __get_user(f->spindown, &uf->spindown); | ||
378 | err |= __get_user(f->spindown_offset, &uf->spindown_offset); | ||
379 | err |= __get_user(f->select_delay, &uf->select_delay); | ||
380 | err |= __get_user(f->rps, &uf->rps); | ||
381 | err |= __get_user(f->tracks, &uf->tracks); | ||
382 | err |= __get_user(f->timeout, &uf->timeout); | ||
383 | err |= __get_user(f->interleave_sect, &uf->interleave_sect); | ||
384 | err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors)); | ||
385 | err |= __get_user(f->flags, &uf->flags); | ||
386 | err |= __get_user(f->read_track, &uf->read_track); | ||
387 | err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect)); | ||
388 | err |= __get_user(f->checkfreq, &uf->checkfreq); | ||
389 | err |= __get_user(f->native_format, &uf->native_format); | ||
390 | if (err) { | ||
391 | err = -EFAULT; | ||
392 | goto out; | ||
393 | } | ||
394 | break; | ||
395 | } | ||
396 | case FDGETDRVSTAT32: | ||
397 | case FDPOLLDRVSTAT32: | ||
398 | karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); | ||
399 | if (!karg) | ||
400 | return -ENOMEM; | ||
401 | break; | ||
402 | case FDGETFDCSTAT32: | ||
403 | karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); | ||
404 | if (!karg) | ||
405 | return -ENOMEM; | ||
406 | break; | ||
407 | case FDWERRORGET32: | ||
408 | karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); | ||
409 | if (!karg) | ||
410 | return -ENOMEM; | ||
411 | break; | ||
412 | default: | ||
413 | return -EINVAL; | ||
414 | } | ||
415 | set_fs(KERNEL_DS); | ||
416 | err = blkdev_driver_ioctl(inode, file, disk, kcmd, (unsigned long)karg); | ||
417 | set_fs(old_fs); | ||
418 | if (err) | ||
419 | goto out; | ||
420 | switch (cmd) { | ||
421 | case FDGETPRM32: | ||
422 | { | ||
423 | struct floppy_struct *f = karg; | ||
424 | struct compat_floppy_struct __user *uf = compat_ptr(arg); | ||
425 | |||
426 | err = __put_user(f->size, &uf->size); | ||
427 | err |= __put_user(f->sect, &uf->sect); | ||
428 | err |= __put_user(f->head, &uf->head); | ||
429 | err |= __put_user(f->track, &uf->track); | ||
430 | err |= __put_user(f->stretch, &uf->stretch); | ||
431 | err |= __put_user(f->gap, &uf->gap); | ||
432 | err |= __put_user(f->rate, &uf->rate); | ||
433 | err |= __put_user(f->spec1, &uf->spec1); | ||
434 | err |= __put_user(f->fmt_gap, &uf->fmt_gap); | ||
435 | err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name); | ||
436 | break; | ||
437 | } | ||
438 | case FDGETDRVPRM32: | ||
439 | { | ||
440 | struct compat_floppy_drive_params __user *uf; | ||
441 | struct floppy_drive_params *f = karg; | ||
442 | |||
443 | uf = compat_ptr(arg); | ||
444 | err = __put_user(f->cmos, &uf->cmos); | ||
445 | err |= __put_user(f->max_dtr, &uf->max_dtr); | ||
446 | err |= __put_user(f->hlt, &uf->hlt); | ||
447 | err |= __put_user(f->hut, &uf->hut); | ||
448 | err |= __put_user(f->srt, &uf->srt); | ||
449 | err |= __put_user(f->spinup, &uf->spinup); | ||
450 | err |= __put_user(f->spindown, &uf->spindown); | ||
451 | err |= __put_user(f->spindown_offset, &uf->spindown_offset); | ||
452 | err |= __put_user(f->select_delay, &uf->select_delay); | ||
453 | err |= __put_user(f->rps, &uf->rps); | ||
454 | err |= __put_user(f->tracks, &uf->tracks); | ||
455 | err |= __put_user(f->timeout, &uf->timeout); | ||
456 | err |= __put_user(f->interleave_sect, &uf->interleave_sect); | ||
457 | err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors)); | ||
458 | err |= __put_user(f->flags, &uf->flags); | ||
459 | err |= __put_user(f->read_track, &uf->read_track); | ||
460 | err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect)); | ||
461 | err |= __put_user(f->checkfreq, &uf->checkfreq); | ||
462 | err |= __put_user(f->native_format, &uf->native_format); | ||
463 | break; | ||
464 | } | ||
465 | case FDGETDRVSTAT32: | ||
466 | case FDPOLLDRVSTAT32: | ||
467 | { | ||
468 | struct compat_floppy_drive_struct __user *uf; | ||
469 | struct floppy_drive_struct *f = karg; | ||
470 | |||
471 | uf = compat_ptr(arg); | ||
472 | err = __put_user(f->flags, &uf->flags); | ||
473 | err |= __put_user(f->spinup_date, &uf->spinup_date); | ||
474 | err |= __put_user(f->select_date, &uf->select_date); | ||
475 | err |= __put_user(f->first_read_date, &uf->first_read_date); | ||
476 | err |= __put_user(f->probed_format, &uf->probed_format); | ||
477 | err |= __put_user(f->track, &uf->track); | ||
478 | err |= __put_user(f->maxblock, &uf->maxblock); | ||
479 | err |= __put_user(f->maxtrack, &uf->maxtrack); | ||
480 | err |= __put_user(f->generation, &uf->generation); | ||
481 | err |= __put_user(f->keep_data, &uf->keep_data); | ||
482 | err |= __put_user(f->fd_ref, &uf->fd_ref); | ||
483 | err |= __put_user(f->fd_device, &uf->fd_device); | ||
484 | err |= __put_user(f->last_checked, &uf->last_checked); | ||
485 | err |= __put_user((u64)f->dmabuf, &uf->dmabuf); | ||
486 | err |= __put_user((u64)f->bufblocks, &uf->bufblocks); | ||
487 | break; | ||
488 | } | ||
489 | case FDGETFDCSTAT32: | ||
490 | { | ||
491 | struct compat_floppy_fdc_state __user *uf; | ||
492 | struct floppy_fdc_state *f = karg; | ||
493 | |||
494 | uf = compat_ptr(arg); | ||
495 | err = __put_user(f->spec1, &uf->spec1); | ||
496 | err |= __put_user(f->spec2, &uf->spec2); | ||
497 | err |= __put_user(f->dtr, &uf->dtr); | ||
498 | err |= __put_user(f->version, &uf->version); | ||
499 | err |= __put_user(f->dor, &uf->dor); | ||
500 | err |= __put_user(f->address, &uf->address); | ||
501 | err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address), | ||
502 | (char *)&f->address + sizeof(f->address), sizeof(int)); | ||
503 | err |= __put_user(f->driver_version, &uf->driver_version); | ||
504 | err |= __copy_to_user(uf->track, f->track, sizeof(f->track)); | ||
505 | break; | ||
506 | } | ||
507 | case FDWERRORGET32: | ||
508 | { | ||
509 | struct compat_floppy_write_errors __user *uf; | ||
510 | struct floppy_write_errors *f = karg; | ||
511 | |||
512 | uf = compat_ptr(arg); | ||
513 | err = __put_user(f->write_errors, &uf->write_errors); | ||
514 | err |= __put_user(f->first_error_sector, &uf->first_error_sector); | ||
515 | err |= __put_user(f->first_error_generation, &uf->first_error_generation); | ||
516 | err |= __put_user(f->last_error_sector, &uf->last_error_sector); | ||
517 | err |= __put_user(f->last_error_generation, &uf->last_error_generation); | ||
518 | err |= __put_user(f->badness, &uf->badness); | ||
519 | break; | ||
520 | } | ||
521 | default: | ||
522 | break; | ||
523 | } | ||
524 | if (err) | ||
525 | err = -EFAULT; | ||
526 | |||
527 | out: | ||
528 | kfree(karg); | ||
529 | return err; | ||
530 | } | ||
531 | |||
206 | struct compat_blk_user_trace_setup { | 532 | struct compat_blk_user_trace_setup { |
207 | char name[32]; | 533 | char name[32]; |
208 | u16 act_mask; | 534 | u16 act_mask; |
@@ -268,6 +594,16 @@ static int compat_blkdev_driver_ioctl(struct inode *inode, struct file *file, | |||
268 | case HDIO_GET_ADDRESS: | 594 | case HDIO_GET_ADDRESS: |
269 | case HDIO_GET_BUSSTATE: | 595 | case HDIO_GET_BUSSTATE: |
270 | return compat_hdio_ioctl(inode, file, disk, cmd, arg); | 596 | return compat_hdio_ioctl(inode, file, disk, cmd, arg); |
597 | case FDSETPRM32: | ||
598 | case FDDEFPRM32: | ||
599 | case FDGETPRM32: | ||
600 | case FDSETDRVPRM32: | ||
601 | case FDGETDRVPRM32: | ||
602 | case FDGETDRVSTAT32: | ||
603 | case FDPOLLDRVSTAT32: | ||
604 | case FDGETFDCSTAT32: | ||
605 | case FDWERRORGET32: | ||
606 | return compat_fd_ioctl(inode, file, disk, cmd, arg); | ||
271 | case CDROMREADAUDIO: | 607 | case CDROMREADAUDIO: |
272 | return compat_cdrom_read_audio(inode, file, disk, cmd, arg); | 608 | return compat_cdrom_read_audio(inode, file, disk, cmd, arg); |
273 | case CDROM_SEND_PACKET: | 609 | case CDROM_SEND_PACKET: |