diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2017-06-27 15:47:56 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-06-29 18:17:39 -0400 |
commit | 229b53c9bf4e1132a4aa6feb9632a7a1f1d08c5c (patch) | |
tree | b307d7b3f113b81f91fd4ca254df39f7ff18ad39 | |
parent | e5f699d443192001613df21f123c5c3483e55888 (diff) |
take floppy compat ioctls to sodding floppy.c
all other drivers recognizing those ioctls are very much *not*
biarch.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | block/compat_ioctl.c | 340 | ||||
-rw-r--r-- | drivers/block/floppy.c | 328 |
2 files changed, 328 insertions, 340 deletions
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 04325b81c2b4..696e0cdd2df1 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c | |||
@@ -4,7 +4,6 @@ | |||
4 | #include <linux/cdrom.h> | 4 | #include <linux/cdrom.h> |
5 | #include <linux/compat.h> | 5 | #include <linux/compat.h> |
6 | #include <linux/elevator.h> | 6 | #include <linux/elevator.h> |
7 | #include <linux/fd.h> | ||
8 | #include <linux/hdreg.h> | 7 | #include <linux/hdreg.h> |
9 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
10 | #include <linux/syscalls.h> | 9 | #include <linux/syscalls.h> |
@@ -209,318 +208,6 @@ static int compat_blkpg_ioctl(struct block_device *bdev, fmode_t mode, | |||
209 | #define BLKBSZSET_32 _IOW(0x12, 113, int) | 208 | #define BLKBSZSET_32 _IOW(0x12, 113, int) |
210 | #define BLKGETSIZE64_32 _IOR(0x12, 114, int) | 209 | #define BLKGETSIZE64_32 _IOR(0x12, 114, int) |
211 | 210 | ||
212 | struct compat_floppy_drive_params { | ||
213 | char cmos; | ||
214 | compat_ulong_t max_dtr; | ||
215 | compat_ulong_t hlt; | ||
216 | compat_ulong_t hut; | ||
217 | compat_ulong_t srt; | ||
218 | compat_ulong_t spinup; | ||
219 | compat_ulong_t spindown; | ||
220 | unsigned char spindown_offset; | ||
221 | unsigned char select_delay; | ||
222 | unsigned char rps; | ||
223 | unsigned char tracks; | ||
224 | compat_ulong_t timeout; | ||
225 | unsigned char interleave_sect; | ||
226 | struct floppy_max_errors max_errors; | ||
227 | char flags; | ||
228 | char read_track; | ||
229 | short autodetect[8]; | ||
230 | compat_int_t checkfreq; | ||
231 | compat_int_t native_format; | ||
232 | }; | ||
233 | |||
234 | struct compat_floppy_drive_struct { | ||
235 | signed char flags; | ||
236 | compat_ulong_t spinup_date; | ||
237 | compat_ulong_t select_date; | ||
238 | compat_ulong_t first_read_date; | ||
239 | short probed_format; | ||
240 | short track; | ||
241 | short maxblock; | ||
242 | short maxtrack; | ||
243 | compat_int_t generation; | ||
244 | compat_int_t keep_data; | ||
245 | compat_int_t fd_ref; | ||
246 | compat_int_t fd_device; | ||
247 | compat_int_t last_checked; | ||
248 | compat_caddr_t dmabuf; | ||
249 | compat_int_t bufblocks; | ||
250 | }; | ||
251 | |||
252 | struct compat_floppy_fdc_state { | ||
253 | compat_int_t spec1; | ||
254 | compat_int_t spec2; | ||
255 | compat_int_t dtr; | ||
256 | unsigned char version; | ||
257 | unsigned char dor; | ||
258 | compat_ulong_t address; | ||
259 | unsigned int rawcmd:2; | ||
260 | unsigned int reset:1; | ||
261 | unsigned int need_configure:1; | ||
262 | unsigned int perp_mode:2; | ||
263 | unsigned int has_fifo:1; | ||
264 | unsigned int driver_version; | ||
265 | unsigned char track[4]; | ||
266 | }; | ||
267 | |||
268 | struct compat_floppy_write_errors { | ||
269 | unsigned int write_errors; | ||
270 | compat_ulong_t first_error_sector; | ||
271 | compat_int_t first_error_generation; | ||
272 | compat_ulong_t last_error_sector; | ||
273 | compat_int_t last_error_generation; | ||
274 | compat_uint_t badness; | ||
275 | }; | ||
276 | |||
277 | #define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) | ||
278 | #define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct) | ||
279 | #define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params) | ||
280 | #define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params) | ||
281 | #define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct) | ||
282 | #define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct) | ||
283 | #define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) | ||
284 | #define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) | ||
285 | |||
286 | static struct { | ||
287 | unsigned int cmd32; | ||
288 | unsigned int cmd; | ||
289 | } fd_ioctl_trans_table[] = { | ||
290 | { FDSETPRM32, FDSETPRM }, | ||
291 | { FDDEFPRM32, FDDEFPRM }, | ||
292 | { FDGETPRM32, FDGETPRM }, | ||
293 | { FDSETDRVPRM32, FDSETDRVPRM }, | ||
294 | { FDGETDRVPRM32, FDGETDRVPRM }, | ||
295 | { FDGETDRVSTAT32, FDGETDRVSTAT }, | ||
296 | { FDPOLLDRVSTAT32, FDPOLLDRVSTAT }, | ||
297 | { FDGETFDCSTAT32, FDGETFDCSTAT }, | ||
298 | { FDWERRORGET32, FDWERRORGET } | ||
299 | }; | ||
300 | |||
301 | #define NR_FD_IOCTL_TRANS ARRAY_SIZE(fd_ioctl_trans_table) | ||
302 | |||
303 | static int compat_fd_ioctl(struct block_device *bdev, fmode_t mode, | ||
304 | unsigned int cmd, unsigned long arg) | ||
305 | { | ||
306 | mm_segment_t old_fs = get_fs(); | ||
307 | void *karg = NULL; | ||
308 | unsigned int kcmd = 0; | ||
309 | int i, err; | ||
310 | |||
311 | for (i = 0; i < NR_FD_IOCTL_TRANS; i++) | ||
312 | if (cmd == fd_ioctl_trans_table[i].cmd32) { | ||
313 | kcmd = fd_ioctl_trans_table[i].cmd; | ||
314 | break; | ||
315 | } | ||
316 | if (!kcmd) | ||
317 | return -EINVAL; | ||
318 | |||
319 | switch (cmd) { | ||
320 | case FDSETPRM32: | ||
321 | case FDDEFPRM32: | ||
322 | case FDGETPRM32: | ||
323 | { | ||
324 | compat_uptr_t name; | ||
325 | struct compat_floppy_struct __user *uf; | ||
326 | struct floppy_struct *f; | ||
327 | |||
328 | uf = compat_ptr(arg); | ||
329 | f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL); | ||
330 | if (!karg) | ||
331 | return -ENOMEM; | ||
332 | if (cmd == FDGETPRM32) | ||
333 | break; | ||
334 | err = __get_user(f->size, &uf->size); | ||
335 | err |= __get_user(f->sect, &uf->sect); | ||
336 | err |= __get_user(f->head, &uf->head); | ||
337 | err |= __get_user(f->track, &uf->track); | ||
338 | err |= __get_user(f->stretch, &uf->stretch); | ||
339 | err |= __get_user(f->gap, &uf->gap); | ||
340 | err |= __get_user(f->rate, &uf->rate); | ||
341 | err |= __get_user(f->spec1, &uf->spec1); | ||
342 | err |= __get_user(f->fmt_gap, &uf->fmt_gap); | ||
343 | err |= __get_user(name, &uf->name); | ||
344 | f->name = compat_ptr(name); | ||
345 | if (err) { | ||
346 | err = -EFAULT; | ||
347 | goto out; | ||
348 | } | ||
349 | break; | ||
350 | } | ||
351 | case FDSETDRVPRM32: | ||
352 | case FDGETDRVPRM32: | ||
353 | { | ||
354 | struct compat_floppy_drive_params __user *uf; | ||
355 | struct floppy_drive_params *f; | ||
356 | |||
357 | uf = compat_ptr(arg); | ||
358 | f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL); | ||
359 | if (!karg) | ||
360 | return -ENOMEM; | ||
361 | if (cmd == FDGETDRVPRM32) | ||
362 | break; | ||
363 | err = __get_user(f->cmos, &uf->cmos); | ||
364 | err |= __get_user(f->max_dtr, &uf->max_dtr); | ||
365 | err |= __get_user(f->hlt, &uf->hlt); | ||
366 | err |= __get_user(f->hut, &uf->hut); | ||
367 | err |= __get_user(f->srt, &uf->srt); | ||
368 | err |= __get_user(f->spinup, &uf->spinup); | ||
369 | err |= __get_user(f->spindown, &uf->spindown); | ||
370 | err |= __get_user(f->spindown_offset, &uf->spindown_offset); | ||
371 | err |= __get_user(f->select_delay, &uf->select_delay); | ||
372 | err |= __get_user(f->rps, &uf->rps); | ||
373 | err |= __get_user(f->tracks, &uf->tracks); | ||
374 | err |= __get_user(f->timeout, &uf->timeout); | ||
375 | err |= __get_user(f->interleave_sect, &uf->interleave_sect); | ||
376 | err |= __copy_from_user(&f->max_errors, &uf->max_errors, sizeof(f->max_errors)); | ||
377 | err |= __get_user(f->flags, &uf->flags); | ||
378 | err |= __get_user(f->read_track, &uf->read_track); | ||
379 | err |= __copy_from_user(f->autodetect, uf->autodetect, sizeof(f->autodetect)); | ||
380 | err |= __get_user(f->checkfreq, &uf->checkfreq); | ||
381 | err |= __get_user(f->native_format, &uf->native_format); | ||
382 | if (err) { | ||
383 | err = -EFAULT; | ||
384 | goto out; | ||
385 | } | ||
386 | break; | ||
387 | } | ||
388 | case FDGETDRVSTAT32: | ||
389 | case FDPOLLDRVSTAT32: | ||
390 | karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL); | ||
391 | if (!karg) | ||
392 | return -ENOMEM; | ||
393 | break; | ||
394 | case FDGETFDCSTAT32: | ||
395 | karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL); | ||
396 | if (!karg) | ||
397 | return -ENOMEM; | ||
398 | break; | ||
399 | case FDWERRORGET32: | ||
400 | karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL); | ||
401 | if (!karg) | ||
402 | return -ENOMEM; | ||
403 | break; | ||
404 | default: | ||
405 | return -EINVAL; | ||
406 | } | ||
407 | set_fs(KERNEL_DS); | ||
408 | err = __blkdev_driver_ioctl(bdev, mode, kcmd, (unsigned long)karg); | ||
409 | set_fs(old_fs); | ||
410 | if (err) | ||
411 | goto out; | ||
412 | switch (cmd) { | ||
413 | case FDGETPRM32: | ||
414 | { | ||
415 | struct floppy_struct *f = karg; | ||
416 | struct compat_floppy_struct __user *uf = compat_ptr(arg); | ||
417 | |||
418 | err = __put_user(f->size, &uf->size); | ||
419 | err |= __put_user(f->sect, &uf->sect); | ||
420 | err |= __put_user(f->head, &uf->head); | ||
421 | err |= __put_user(f->track, &uf->track); | ||
422 | err |= __put_user(f->stretch, &uf->stretch); | ||
423 | err |= __put_user(f->gap, &uf->gap); | ||
424 | err |= __put_user(f->rate, &uf->rate); | ||
425 | err |= __put_user(f->spec1, &uf->spec1); | ||
426 | err |= __put_user(f->fmt_gap, &uf->fmt_gap); | ||
427 | err |= __put_user((u64)f->name, (compat_caddr_t __user *)&uf->name); | ||
428 | break; | ||
429 | } | ||
430 | case FDGETDRVPRM32: | ||
431 | { | ||
432 | struct compat_floppy_drive_params __user *uf; | ||
433 | struct floppy_drive_params *f = karg; | ||
434 | |||
435 | uf = compat_ptr(arg); | ||
436 | err = __put_user(f->cmos, &uf->cmos); | ||
437 | err |= __put_user(f->max_dtr, &uf->max_dtr); | ||
438 | err |= __put_user(f->hlt, &uf->hlt); | ||
439 | err |= __put_user(f->hut, &uf->hut); | ||
440 | err |= __put_user(f->srt, &uf->srt); | ||
441 | err |= __put_user(f->spinup, &uf->spinup); | ||
442 | err |= __put_user(f->spindown, &uf->spindown); | ||
443 | err |= __put_user(f->spindown_offset, &uf->spindown_offset); | ||
444 | err |= __put_user(f->select_delay, &uf->select_delay); | ||
445 | err |= __put_user(f->rps, &uf->rps); | ||
446 | err |= __put_user(f->tracks, &uf->tracks); | ||
447 | err |= __put_user(f->timeout, &uf->timeout); | ||
448 | err |= __put_user(f->interleave_sect, &uf->interleave_sect); | ||
449 | err |= __copy_to_user(&uf->max_errors, &f->max_errors, sizeof(f->max_errors)); | ||
450 | err |= __put_user(f->flags, &uf->flags); | ||
451 | err |= __put_user(f->read_track, &uf->read_track); | ||
452 | err |= __copy_to_user(uf->autodetect, f->autodetect, sizeof(f->autodetect)); | ||
453 | err |= __put_user(f->checkfreq, &uf->checkfreq); | ||
454 | err |= __put_user(f->native_format, &uf->native_format); | ||
455 | break; | ||
456 | } | ||
457 | case FDGETDRVSTAT32: | ||
458 | case FDPOLLDRVSTAT32: | ||
459 | { | ||
460 | struct compat_floppy_drive_struct __user *uf; | ||
461 | struct floppy_drive_struct *f = karg; | ||
462 | |||
463 | uf = compat_ptr(arg); | ||
464 | err = __put_user(f->flags, &uf->flags); | ||
465 | err |= __put_user(f->spinup_date, &uf->spinup_date); | ||
466 | err |= __put_user(f->select_date, &uf->select_date); | ||
467 | err |= __put_user(f->first_read_date, &uf->first_read_date); | ||
468 | err |= __put_user(f->probed_format, &uf->probed_format); | ||
469 | err |= __put_user(f->track, &uf->track); | ||
470 | err |= __put_user(f->maxblock, &uf->maxblock); | ||
471 | err |= __put_user(f->maxtrack, &uf->maxtrack); | ||
472 | err |= __put_user(f->generation, &uf->generation); | ||
473 | err |= __put_user(f->keep_data, &uf->keep_data); | ||
474 | err |= __put_user(f->fd_ref, &uf->fd_ref); | ||
475 | err |= __put_user(f->fd_device, &uf->fd_device); | ||
476 | err |= __put_user(f->last_checked, &uf->last_checked); | ||
477 | err |= __put_user((u64)f->dmabuf, &uf->dmabuf); | ||
478 | err |= __put_user((u64)f->bufblocks, &uf->bufblocks); | ||
479 | break; | ||
480 | } | ||
481 | case FDGETFDCSTAT32: | ||
482 | { | ||
483 | struct compat_floppy_fdc_state __user *uf; | ||
484 | struct floppy_fdc_state *f = karg; | ||
485 | |||
486 | uf = compat_ptr(arg); | ||
487 | err = __put_user(f->spec1, &uf->spec1); | ||
488 | err |= __put_user(f->spec2, &uf->spec2); | ||
489 | err |= __put_user(f->dtr, &uf->dtr); | ||
490 | err |= __put_user(f->version, &uf->version); | ||
491 | err |= __put_user(f->dor, &uf->dor); | ||
492 | err |= __put_user(f->address, &uf->address); | ||
493 | err |= __copy_to_user((char __user *)&uf->address + sizeof(uf->address), | ||
494 | (char *)&f->address + sizeof(f->address), sizeof(int)); | ||
495 | err |= __put_user(f->driver_version, &uf->driver_version); | ||
496 | err |= __copy_to_user(uf->track, f->track, sizeof(f->track)); | ||
497 | break; | ||
498 | } | ||
499 | case FDWERRORGET32: | ||
500 | { | ||
501 | struct compat_floppy_write_errors __user *uf; | ||
502 | struct floppy_write_errors *f = karg; | ||
503 | |||
504 | uf = compat_ptr(arg); | ||
505 | err = __put_user(f->write_errors, &uf->write_errors); | ||
506 | err |= __put_user(f->first_error_sector, &uf->first_error_sector); | ||
507 | err |= __put_user(f->first_error_generation, &uf->first_error_generation); | ||
508 | err |= __put_user(f->last_error_sector, &uf->last_error_sector); | ||
509 | err |= __put_user(f->last_error_generation, &uf->last_error_generation); | ||
510 | err |= __put_user(f->badness, &uf->badness); | ||
511 | break; | ||
512 | } | ||
513 | default: | ||
514 | break; | ||
515 | } | ||
516 | if (err) | ||
517 | err = -EFAULT; | ||
518 | |||
519 | out: | ||
520 | kfree(karg); | ||
521 | return err; | ||
522 | } | ||
523 | |||
524 | static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, | 211 | static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, |
525 | unsigned cmd, unsigned long arg) | 212 | unsigned cmd, unsigned long arg) |
526 | { | 213 | { |
@@ -537,16 +224,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, | |||
537 | case HDIO_GET_ADDRESS: | 224 | case HDIO_GET_ADDRESS: |
538 | case HDIO_GET_BUSSTATE: | 225 | case HDIO_GET_BUSSTATE: |
539 | return compat_hdio_ioctl(bdev, mode, cmd, arg); | 226 | return compat_hdio_ioctl(bdev, mode, cmd, arg); |
540 | case FDSETPRM32: | ||
541 | case FDDEFPRM32: | ||
542 | case FDGETPRM32: | ||
543 | case FDSETDRVPRM32: | ||
544 | case FDGETDRVPRM32: | ||
545 | case FDGETDRVSTAT32: | ||
546 | case FDPOLLDRVSTAT32: | ||
547 | case FDGETFDCSTAT32: | ||
548 | case FDWERRORGET32: | ||
549 | return compat_fd_ioctl(bdev, mode, cmd, arg); | ||
550 | case CDROMREADAUDIO: | 227 | case CDROMREADAUDIO: |
551 | return compat_cdrom_read_audio(bdev, mode, cmd, arg); | 228 | return compat_cdrom_read_audio(bdev, mode, cmd, arg); |
552 | case CDROM_SEND_PACKET: | 229 | case CDROM_SEND_PACKET: |
@@ -566,23 +243,6 @@ static int compat_blkdev_driver_ioctl(struct block_device *bdev, fmode_t mode, | |||
566 | case HDIO_DRIVE_CMD: | 243 | case HDIO_DRIVE_CMD: |
567 | /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ | 244 | /* 0x330 is reserved -- it used to be HDIO_GETGEO_BIG */ |
568 | case 0x330: | 245 | case 0x330: |
569 | /* 0x02 -- Floppy ioctls */ | ||
570 | case FDMSGON: | ||
571 | case FDMSGOFF: | ||
572 | case FDSETEMSGTRESH: | ||
573 | case FDFLUSH: | ||
574 | case FDWERRORCLR: | ||
575 | case FDSETMAXERRS: | ||
576 | case FDGETMAXERRS: | ||
577 | case FDGETDRVTYP: | ||
578 | case FDEJECT: | ||
579 | case FDCLRPRM: | ||
580 | case FDFMTBEG: | ||
581 | case FDFMTEND: | ||
582 | case FDRESET: | ||
583 | case FDTWADDLE: | ||
584 | case FDFMTTRK: | ||
585 | case FDRAWCMD: | ||
586 | /* CDROM stuff */ | 246 | /* CDROM stuff */ |
587 | case CDROMPAUSE: | 247 | case CDROMPAUSE: |
588 | case CDROMRESUME: | 248 | case CDROMRESUME: |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 60d4c7653178..fb9cfbd1807d 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
@@ -192,6 +192,7 @@ static int print_unex = 1; | |||
192 | #include <linux/io.h> | 192 | #include <linux/io.h> |
193 | #include <linux/uaccess.h> | 193 | #include <linux/uaccess.h> |
194 | #include <linux/async.h> | 194 | #include <linux/async.h> |
195 | #include <linux/compat.h> | ||
195 | 196 | ||
196 | /* | 197 | /* |
197 | * PS/2 floppies have much slower step rates than regular floppies. | 198 | * PS/2 floppies have much slower step rates than regular floppies. |
@@ -3568,6 +3569,330 @@ static int fd_ioctl(struct block_device *bdev, fmode_t mode, | |||
3568 | return ret; | 3569 | return ret; |
3569 | } | 3570 | } |
3570 | 3571 | ||
3572 | #ifdef CONFIG_COMPAT | ||
3573 | |||
3574 | struct compat_floppy_drive_params { | ||
3575 | char cmos; | ||
3576 | compat_ulong_t max_dtr; | ||
3577 | compat_ulong_t hlt; | ||
3578 | compat_ulong_t hut; | ||
3579 | compat_ulong_t srt; | ||
3580 | compat_ulong_t spinup; | ||
3581 | compat_ulong_t spindown; | ||
3582 | unsigned char spindown_offset; | ||
3583 | unsigned char select_delay; | ||
3584 | unsigned char rps; | ||
3585 | unsigned char tracks; | ||
3586 | compat_ulong_t timeout; | ||
3587 | unsigned char interleave_sect; | ||
3588 | struct floppy_max_errors max_errors; | ||
3589 | char flags; | ||
3590 | char read_track; | ||
3591 | short autodetect[8]; | ||
3592 | compat_int_t checkfreq; | ||
3593 | compat_int_t native_format; | ||
3594 | }; | ||
3595 | |||
3596 | struct compat_floppy_drive_struct { | ||
3597 | signed char flags; | ||
3598 | compat_ulong_t spinup_date; | ||
3599 | compat_ulong_t select_date; | ||
3600 | compat_ulong_t first_read_date; | ||
3601 | short probed_format; | ||
3602 | short track; | ||
3603 | short maxblock; | ||
3604 | short maxtrack; | ||
3605 | compat_int_t generation; | ||
3606 | compat_int_t keep_data; | ||
3607 | compat_int_t fd_ref; | ||
3608 | compat_int_t fd_device; | ||
3609 | compat_int_t last_checked; | ||
3610 | compat_caddr_t dmabuf; | ||
3611 | compat_int_t bufblocks; | ||
3612 | }; | ||
3613 | |||
3614 | struct compat_floppy_fdc_state { | ||
3615 | compat_int_t spec1; | ||
3616 | compat_int_t spec2; | ||
3617 | compat_int_t dtr; | ||
3618 | unsigned char version; | ||
3619 | unsigned char dor; | ||
3620 | compat_ulong_t address; | ||
3621 | unsigned int rawcmd:2; | ||
3622 | unsigned int reset:1; | ||
3623 | unsigned int need_configure:1; | ||
3624 | unsigned int perp_mode:2; | ||
3625 | unsigned int has_fifo:1; | ||
3626 | unsigned int driver_version; | ||
3627 | unsigned char track[4]; | ||
3628 | }; | ||
3629 | |||
3630 | struct compat_floppy_write_errors { | ||
3631 | unsigned int write_errors; | ||
3632 | compat_ulong_t first_error_sector; | ||
3633 | compat_int_t first_error_generation; | ||
3634 | compat_ulong_t last_error_sector; | ||
3635 | compat_int_t last_error_generation; | ||
3636 | compat_uint_t badness; | ||
3637 | }; | ||
3638 | |||
3639 | #define FDSETPRM32 _IOW(2, 0x42, struct compat_floppy_struct) | ||
3640 | #define FDDEFPRM32 _IOW(2, 0x43, struct compat_floppy_struct) | ||
3641 | #define FDSETDRVPRM32 _IOW(2, 0x90, struct compat_floppy_drive_params) | ||
3642 | #define FDGETDRVPRM32 _IOR(2, 0x11, struct compat_floppy_drive_params) | ||
3643 | #define FDGETDRVSTAT32 _IOR(2, 0x12, struct compat_floppy_drive_struct) | ||
3644 | #define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct compat_floppy_drive_struct) | ||
3645 | #define FDGETFDCSTAT32 _IOR(2, 0x15, struct compat_floppy_fdc_state) | ||
3646 | #define FDWERRORGET32 _IOR(2, 0x17, struct compat_floppy_write_errors) | ||
3647 | |||
3648 | static int compat_set_geometry(struct block_device *bdev, fmode_t mode, unsigned int cmd, | ||
3649 | struct compat_floppy_struct __user *arg) | ||
3650 | { | ||
3651 | struct floppy_struct v; | ||
3652 | int drive, type; | ||
3653 | int err; | ||
3654 | |||
3655 | BUILD_BUG_ON(offsetof(struct floppy_struct, name) != | ||
3656 | offsetof(struct compat_floppy_struct, name)); | ||
3657 | |||
3658 | if (!(mode & (FMODE_WRITE | FMODE_WRITE_IOCTL))) | ||
3659 | return -EPERM; | ||
3660 | |||
3661 | memset(&v, 0, sizeof(struct floppy_struct)); | ||
3662 | if (copy_from_user(&v, arg, offsetof(struct floppy_struct, name))) | ||
3663 | return -EFAULT; | ||
3664 | |||
3665 | mutex_lock(&floppy_mutex); | ||
3666 | drive = (long)bdev->bd_disk->private_data; | ||
3667 | type = ITYPE(UDRS->fd_device); | ||
3668 | err = set_geometry(cmd == FDSETPRM32 ? FDSETPRM : FDDEFPRM, | ||
3669 | &v, drive, type, bdev); | ||
3670 | mutex_unlock(&floppy_mutex); | ||
3671 | return err; | ||
3672 | } | ||
3673 | |||
3674 | static int compat_get_prm(int drive, | ||
3675 | struct compat_floppy_struct __user *arg) | ||
3676 | { | ||
3677 | struct compat_floppy_struct v; | ||
3678 | struct floppy_struct *p; | ||
3679 | int err; | ||
3680 | |||
3681 | memset(&v, 0, sizeof(v)); | ||
3682 | mutex_lock(&floppy_mutex); | ||
3683 | err = get_floppy_geometry(drive, ITYPE(UDRS->fd_device), &p); | ||
3684 | if (err) { | ||
3685 | mutex_unlock(&floppy_mutex); | ||
3686 | return err; | ||
3687 | } | ||
3688 | memcpy(&v, p, offsetof(struct floppy_struct, name)); | ||
3689 | mutex_unlock(&floppy_mutex); | ||
3690 | if (copy_to_user(arg, &v, sizeof(struct compat_floppy_struct))) | ||
3691 | return -EFAULT; | ||
3692 | return 0; | ||
3693 | } | ||
3694 | |||
3695 | static int compat_setdrvprm(int drive, | ||
3696 | struct compat_floppy_drive_params __user *arg) | ||
3697 | { | ||
3698 | struct compat_floppy_drive_params v; | ||
3699 | |||
3700 | if (!capable(CAP_SYS_ADMIN)) | ||
3701 | return -EPERM; | ||
3702 | if (copy_from_user(&v, arg, sizeof(struct compat_floppy_drive_params))) | ||
3703 | return -EFAULT; | ||
3704 | mutex_lock(&floppy_mutex); | ||
3705 | UDP->cmos = v.cmos; | ||
3706 | UDP->max_dtr = v.max_dtr; | ||
3707 | UDP->hlt = v.hlt; | ||
3708 | UDP->hut = v.hut; | ||
3709 | UDP->srt = v.srt; | ||
3710 | UDP->spinup = v.spinup; | ||
3711 | UDP->spindown = v.spindown; | ||
3712 | UDP->spindown_offset = v.spindown_offset; | ||
3713 | UDP->select_delay = v.select_delay; | ||
3714 | UDP->rps = v.rps; | ||
3715 | UDP->tracks = v.tracks; | ||
3716 | UDP->timeout = v.timeout; | ||
3717 | UDP->interleave_sect = v.interleave_sect; | ||
3718 | UDP->max_errors = v.max_errors; | ||
3719 | UDP->flags = v.flags; | ||
3720 | UDP->read_track = v.read_track; | ||
3721 | memcpy(UDP->autodetect, v.autodetect, sizeof(v.autodetect)); | ||
3722 | UDP->checkfreq = v.checkfreq; | ||
3723 | UDP->native_format = v.native_format; | ||
3724 | mutex_unlock(&floppy_mutex); | ||
3725 | return 0; | ||
3726 | } | ||
3727 | |||
3728 | static int compat_getdrvprm(int drive, | ||
3729 | struct compat_floppy_drive_params __user *arg) | ||
3730 | { | ||
3731 | struct compat_floppy_drive_params v; | ||
3732 | |||
3733 | memset(&v, 0, sizeof(struct compat_floppy_drive_params)); | ||
3734 | mutex_lock(&floppy_mutex); | ||
3735 | v.cmos = UDP->cmos; | ||
3736 | v.max_dtr = UDP->max_dtr; | ||
3737 | v.hlt = UDP->hlt; | ||
3738 | v.hut = UDP->hut; | ||
3739 | v.srt = UDP->srt; | ||
3740 | v.spinup = UDP->spinup; | ||
3741 | v.spindown = UDP->spindown; | ||
3742 | v.spindown_offset = UDP->spindown_offset; | ||
3743 | v.select_delay = UDP->select_delay; | ||
3744 | v.rps = UDP->rps; | ||
3745 | v.tracks = UDP->tracks; | ||
3746 | v.timeout = UDP->timeout; | ||
3747 | v.interleave_sect = UDP->interleave_sect; | ||
3748 | v.max_errors = UDP->max_errors; | ||
3749 | v.flags = UDP->flags; | ||
3750 | v.read_track = UDP->read_track; | ||
3751 | memcpy(v.autodetect, UDP->autodetect, sizeof(v.autodetect)); | ||
3752 | v.checkfreq = UDP->checkfreq; | ||
3753 | v.native_format = UDP->native_format; | ||
3754 | mutex_unlock(&floppy_mutex); | ||
3755 | |||
3756 | if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_params))) | ||
3757 | return -EFAULT; | ||
3758 | return 0; | ||
3759 | } | ||
3760 | |||
3761 | static int compat_getdrvstat(int drive, bool poll, | ||
3762 | struct compat_floppy_drive_struct __user *arg) | ||
3763 | { | ||
3764 | struct compat_floppy_drive_struct v; | ||
3765 | |||
3766 | memset(&v, 0, sizeof(struct compat_floppy_drive_struct)); | ||
3767 | mutex_lock(&floppy_mutex); | ||
3768 | |||
3769 | if (poll) { | ||
3770 | if (lock_fdc(drive)) | ||
3771 | goto Eintr; | ||
3772 | if (poll_drive(true, FD_RAW_NEED_DISK) == -EINTR) | ||
3773 | goto Eintr; | ||
3774 | process_fd_request(); | ||
3775 | } | ||
3776 | v.spinup_date = UDRS->spinup_date; | ||
3777 | v.select_date = UDRS->select_date; | ||
3778 | v.first_read_date = UDRS->first_read_date; | ||
3779 | v.probed_format = UDRS->probed_format; | ||
3780 | v.track = UDRS->track; | ||
3781 | v.maxblock = UDRS->maxblock; | ||
3782 | v.maxtrack = UDRS->maxtrack; | ||
3783 | v.generation = UDRS->generation; | ||
3784 | v.keep_data = UDRS->keep_data; | ||
3785 | v.fd_ref = UDRS->fd_ref; | ||
3786 | v.fd_device = UDRS->fd_device; | ||
3787 | v.last_checked = UDRS->last_checked; | ||
3788 | v.dmabuf = (uintptr_t)UDRS->dmabuf; | ||
3789 | v.bufblocks = UDRS->bufblocks; | ||
3790 | mutex_unlock(&floppy_mutex); | ||
3791 | |||
3792 | if (copy_from_user(arg, &v, sizeof(struct compat_floppy_drive_struct))) | ||
3793 | return -EFAULT; | ||
3794 | return 0; | ||
3795 | Eintr: | ||
3796 | mutex_unlock(&floppy_mutex); | ||
3797 | return -EINTR; | ||
3798 | } | ||
3799 | |||
3800 | static int compat_getfdcstat(int drive, | ||
3801 | struct compat_floppy_fdc_state __user *arg) | ||
3802 | { | ||
3803 | struct compat_floppy_fdc_state v32; | ||
3804 | struct floppy_fdc_state v; | ||
3805 | |||
3806 | mutex_lock(&floppy_mutex); | ||
3807 | v = *UFDCS; | ||
3808 | mutex_unlock(&floppy_mutex); | ||
3809 | |||
3810 | memset(&v32, 0, sizeof(struct compat_floppy_fdc_state)); | ||
3811 | v32.spec1 = v.spec1; | ||
3812 | v32.spec2 = v.spec2; | ||
3813 | v32.dtr = v.dtr; | ||
3814 | v32.version = v.version; | ||
3815 | v32.dor = v.dor; | ||
3816 | v32.address = v.address; | ||
3817 | v32.rawcmd = v.rawcmd; | ||
3818 | v32.reset = v.reset; | ||
3819 | v32.need_configure = v.need_configure; | ||
3820 | v32.perp_mode = v.perp_mode; | ||
3821 | v32.has_fifo = v.has_fifo; | ||
3822 | v32.driver_version = v.driver_version; | ||
3823 | memcpy(v32.track, v.track, 4); | ||
3824 | if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_fdc_state))) | ||
3825 | return -EFAULT; | ||
3826 | return 0; | ||
3827 | } | ||
3828 | |||
3829 | static int compat_werrorget(int drive, | ||
3830 | struct compat_floppy_write_errors __user *arg) | ||
3831 | { | ||
3832 | struct compat_floppy_write_errors v32; | ||
3833 | struct floppy_write_errors v; | ||
3834 | |||
3835 | memset(&v32, 0, sizeof(struct compat_floppy_write_errors)); | ||
3836 | mutex_lock(&floppy_mutex); | ||
3837 | v = *UDRWE; | ||
3838 | mutex_unlock(&floppy_mutex); | ||
3839 | v32.write_errors = v.write_errors; | ||
3840 | v32.first_error_sector = v.first_error_sector; | ||
3841 | v32.first_error_generation = v.first_error_generation; | ||
3842 | v32.last_error_sector = v.last_error_sector; | ||
3843 | v32.last_error_generation = v.last_error_generation; | ||
3844 | v32.badness = v.badness; | ||
3845 | if (copy_to_user(arg, &v32, sizeof(struct compat_floppy_write_errors))) | ||
3846 | return -EFAULT; | ||
3847 | return 0; | ||
3848 | } | ||
3849 | |||
3850 | static int fd_compat_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, | ||
3851 | unsigned long param) | ||
3852 | { | ||
3853 | int drive = (long)bdev->bd_disk->private_data; | ||
3854 | switch (cmd) { | ||
3855 | case FDMSGON: | ||
3856 | case FDMSGOFF: | ||
3857 | case FDSETEMSGTRESH: | ||
3858 | case FDFLUSH: | ||
3859 | case FDWERRORCLR: | ||
3860 | case FDEJECT: | ||
3861 | case FDCLRPRM: | ||
3862 | case FDFMTBEG: | ||
3863 | case FDRESET: | ||
3864 | case FDTWADDLE: | ||
3865 | return fd_ioctl(bdev, mode, cmd, param); | ||
3866 | case FDSETMAXERRS: | ||
3867 | case FDGETMAXERRS: | ||
3868 | case FDGETDRVTYP: | ||
3869 | case FDFMTEND: | ||
3870 | case FDFMTTRK: | ||
3871 | case FDRAWCMD: | ||
3872 | return fd_ioctl(bdev, mode, cmd, | ||
3873 | (unsigned long)compat_ptr(param)); | ||
3874 | case FDSETPRM32: | ||
3875 | case FDDEFPRM32: | ||
3876 | return compat_set_geometry(bdev, mode, cmd, compat_ptr(param)); | ||
3877 | case FDGETPRM32: | ||
3878 | return compat_get_prm(drive, compat_ptr(param)); | ||
3879 | case FDSETDRVPRM32: | ||
3880 | return compat_setdrvprm(drive, compat_ptr(param)); | ||
3881 | case FDGETDRVPRM32: | ||
3882 | return compat_getdrvprm(drive, compat_ptr(param)); | ||
3883 | case FDPOLLDRVSTAT32: | ||
3884 | return compat_getdrvstat(drive, true, compat_ptr(param)); | ||
3885 | case FDGETDRVSTAT32: | ||
3886 | return compat_getdrvstat(drive, false, compat_ptr(param)); | ||
3887 | case FDGETFDCSTAT32: | ||
3888 | return compat_getfdcstat(drive, compat_ptr(param)); | ||
3889 | case FDWERRORGET32: | ||
3890 | return compat_werrorget(drive, compat_ptr(param)); | ||
3891 | } | ||
3892 | return -EINVAL; | ||
3893 | } | ||
3894 | #endif | ||
3895 | |||
3571 | static void __init config_types(void) | 3896 | static void __init config_types(void) |
3572 | { | 3897 | { |
3573 | bool has_drive = false; | 3898 | bool has_drive = false; |
@@ -3885,6 +4210,9 @@ static const struct block_device_operations floppy_fops = { | |||
3885 | .getgeo = fd_getgeo, | 4210 | .getgeo = fd_getgeo, |
3886 | .check_events = floppy_check_events, | 4211 | .check_events = floppy_check_events, |
3887 | .revalidate_disk = floppy_revalidate, | 4212 | .revalidate_disk = floppy_revalidate, |
4213 | #ifdef CONFIG_COMPAT | ||
4214 | .compat_ioctl = fd_compat_ioctl, | ||
4215 | #endif | ||
3888 | }; | 4216 | }; |
3889 | 4217 | ||
3890 | /* | 4218 | /* |