| .. | .. |
|---|
| 7 | 7 | License. See linux/COPYING for more information. |
|---|
| 8 | 8 | |
|---|
| 9 | 9 | Uniform CD-ROM driver for Linux. |
|---|
| 10 | | - See Documentation/cdrom/cdrom-standard.tex for usage information. |
|---|
| 10 | + See Documentation/cdrom/cdrom-standard.rst for usage information. |
|---|
| 11 | 11 | |
|---|
| 12 | 12 | The routines in the file provide a uniform interface between the |
|---|
| 13 | 13 | software that uses CD-ROMs and the various low-level drivers that |
|---|
| .. | .. |
|---|
| 586 | 586 | return 0; |
|---|
| 587 | 587 | } |
|---|
| 588 | 588 | |
|---|
| 589 | | -int register_cdrom(struct cdrom_device_info *cdi) |
|---|
| 589 | +int register_cdrom(struct gendisk *disk, struct cdrom_device_info *cdi) |
|---|
| 590 | 590 | { |
|---|
| 591 | 591 | static char banner_printed; |
|---|
| 592 | 592 | const struct cdrom_device_ops *cdo = cdi->ops; |
|---|
| .. | .. |
|---|
| 601 | 601 | cdrom_sysctl_register(); |
|---|
| 602 | 602 | } |
|---|
| 603 | 603 | |
|---|
| 604 | + cdi->disk = disk; |
|---|
| 605 | + disk->cdi = cdi; |
|---|
| 606 | + |
|---|
| 604 | 607 | ENSURE(cdo, drive_status, CDC_DRIVE_STATUS); |
|---|
| 605 | | - if (cdo->check_events == NULL && cdo->media_changed == NULL) |
|---|
| 608 | + if (cdo->check_events == NULL) |
|---|
| 606 | 609 | WARN_ON_ONCE(cdo->capability & (CDC_MEDIA_CHANGED | CDC_SELECT_DISC)); |
|---|
| 607 | 610 | ENSURE(cdo, tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY); |
|---|
| 608 | 611 | ENSURE(cdo, lock_door, CDC_LOCK); |
|---|
| .. | .. |
|---|
| 1416 | 1419 | |
|---|
| 1417 | 1420 | if (cdi->ops->check_events) |
|---|
| 1418 | 1421 | cdi->ops->check_events(cdi, 0, slot); |
|---|
| 1419 | | - else |
|---|
| 1420 | | - cdi->ops->media_changed(cdi, slot); |
|---|
| 1421 | 1422 | |
|---|
| 1422 | 1423 | if (slot == CDSL_NONE) { |
|---|
| 1423 | 1424 | /* set media changed bits, on both queues */ |
|---|
| .. | .. |
|---|
| 1514 | 1515 | return ret; |
|---|
| 1515 | 1516 | |
|---|
| 1516 | 1517 | /* changed since last call? */ |
|---|
| 1517 | | - if (cdi->ops->check_events) { |
|---|
| 1518 | | - BUG_ON(!queue); /* shouldn't be called from VFS path */ |
|---|
| 1519 | | - cdrom_update_events(cdi, DISK_EVENT_MEDIA_CHANGE); |
|---|
| 1520 | | - changed = cdi->ioctl_events & DISK_EVENT_MEDIA_CHANGE; |
|---|
| 1521 | | - cdi->ioctl_events = 0; |
|---|
| 1522 | | - } else |
|---|
| 1523 | | - changed = cdi->ops->media_changed(cdi, CDSL_CURRENT); |
|---|
| 1518 | + BUG_ON(!queue); /* shouldn't be called from VFS path */ |
|---|
| 1519 | + cdrom_update_events(cdi, DISK_EVENT_MEDIA_CHANGE); |
|---|
| 1520 | + changed = cdi->ioctl_events & DISK_EVENT_MEDIA_CHANGE; |
|---|
| 1521 | + cdi->ioctl_events = 0; |
|---|
| 1524 | 1522 | |
|---|
| 1525 | 1523 | if (changed) { |
|---|
| 1526 | 1524 | cdi->mc_flags = 0x3; /* set bit on both queues */ |
|---|
| .. | .. |
|---|
| 1530 | 1528 | |
|---|
| 1531 | 1529 | cdi->mc_flags &= ~mask; /* clear bit */ |
|---|
| 1532 | 1530 | return ret; |
|---|
| 1533 | | -} |
|---|
| 1534 | | - |
|---|
| 1535 | | -int cdrom_media_changed(struct cdrom_device_info *cdi) |
|---|
| 1536 | | -{ |
|---|
| 1537 | | - /* This talks to the VFS, which doesn't like errors - just 1 or 0. |
|---|
| 1538 | | - * Returning "0" is always safe (media hasn't been changed). Do that |
|---|
| 1539 | | - * if the low-level cdrom driver dosn't support media changed. */ |
|---|
| 1540 | | - if (cdi == NULL || cdi->ops->media_changed == NULL) |
|---|
| 1541 | | - return 0; |
|---|
| 1542 | | - if (!CDROM_CAN(CDC_MEDIA_CHANGED)) |
|---|
| 1543 | | - return 0; |
|---|
| 1544 | | - return media_changed(cdi, 0); |
|---|
| 1545 | 1531 | } |
|---|
| 1546 | 1532 | |
|---|
| 1547 | 1533 | /* Requests to the low-level drivers will /always/ be done in the |
|---|
| .. | .. |
|---|
| 2292 | 2278 | return cdrom_read_cdda_old(cdi, ubuf, lba, nframes); |
|---|
| 2293 | 2279 | } |
|---|
| 2294 | 2280 | |
|---|
| 2295 | | -static int cdrom_ioctl_multisession(struct cdrom_device_info *cdi, |
|---|
| 2296 | | - void __user *argp) |
|---|
| 2281 | +int cdrom_multisession(struct cdrom_device_info *cdi, |
|---|
| 2282 | + struct cdrom_multisession *info) |
|---|
| 2297 | 2283 | { |
|---|
| 2298 | | - struct cdrom_multisession ms_info; |
|---|
| 2299 | 2284 | u8 requested_format; |
|---|
| 2300 | 2285 | int ret; |
|---|
| 2301 | | - |
|---|
| 2302 | | - cd_dbg(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); |
|---|
| 2303 | 2286 | |
|---|
| 2304 | 2287 | if (!(cdi->ops->capability & CDC_MULTI_SESSION)) |
|---|
| 2305 | 2288 | return -ENOSYS; |
|---|
| 2306 | 2289 | |
|---|
| 2307 | | - if (copy_from_user(&ms_info, argp, sizeof(ms_info))) |
|---|
| 2308 | | - return -EFAULT; |
|---|
| 2309 | | - |
|---|
| 2310 | | - requested_format = ms_info.addr_format; |
|---|
| 2290 | + requested_format = info->addr_format; |
|---|
| 2311 | 2291 | if (requested_format != CDROM_MSF && requested_format != CDROM_LBA) |
|---|
| 2312 | 2292 | return -EINVAL; |
|---|
| 2313 | | - ms_info.addr_format = CDROM_LBA; |
|---|
| 2293 | + info->addr_format = CDROM_LBA; |
|---|
| 2314 | 2294 | |
|---|
| 2315 | | - ret = cdi->ops->get_last_session(cdi, &ms_info); |
|---|
| 2295 | + ret = cdi->ops->get_last_session(cdi, info); |
|---|
| 2296 | + if (!ret) |
|---|
| 2297 | + sanitize_format(&info->addr, &info->addr_format, |
|---|
| 2298 | + requested_format); |
|---|
| 2299 | + return ret; |
|---|
| 2300 | +} |
|---|
| 2301 | +EXPORT_SYMBOL_GPL(cdrom_multisession); |
|---|
| 2302 | + |
|---|
| 2303 | +static int cdrom_ioctl_multisession(struct cdrom_device_info *cdi, |
|---|
| 2304 | + void __user *argp) |
|---|
| 2305 | +{ |
|---|
| 2306 | + struct cdrom_multisession info; |
|---|
| 2307 | + int ret; |
|---|
| 2308 | + |
|---|
| 2309 | + cd_dbg(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); |
|---|
| 2310 | + |
|---|
| 2311 | + if (copy_from_user(&info, argp, sizeof(info))) |
|---|
| 2312 | + return -EFAULT; |
|---|
| 2313 | + ret = cdrom_multisession(cdi, &info); |
|---|
| 2316 | 2314 | if (ret) |
|---|
| 2317 | 2315 | return ret; |
|---|
| 2318 | | - |
|---|
| 2319 | | - sanitize_format(&ms_info.addr, &ms_info.addr_format, requested_format); |
|---|
| 2320 | | - |
|---|
| 2321 | | - if (copy_to_user(argp, &ms_info, sizeof(ms_info))) |
|---|
| 2316 | + if (copy_to_user(argp, &info, sizeof(info))) |
|---|
| 2322 | 2317 | return -EFAULT; |
|---|
| 2323 | 2318 | |
|---|
| 2324 | 2319 | cd_dbg(CD_DO_IOCTL, "CDROMMULTISESSION successful\n"); |
|---|
| 2325 | | - return 0; |
|---|
| 2320 | + return ret; |
|---|
| 2326 | 2321 | } |
|---|
| 2327 | 2322 | |
|---|
| 2328 | 2323 | static int cdrom_ioctl_eject(struct cdrom_device_info *cdi) |
|---|
| .. | .. |
|---|
| 2663 | 2658 | return 0; |
|---|
| 2664 | 2659 | } |
|---|
| 2665 | 2660 | |
|---|
| 2661 | +int cdrom_read_tocentry(struct cdrom_device_info *cdi, |
|---|
| 2662 | + struct cdrom_tocentry *entry) |
|---|
| 2663 | +{ |
|---|
| 2664 | + u8 requested_format = entry->cdte_format; |
|---|
| 2665 | + int ret; |
|---|
| 2666 | + |
|---|
| 2667 | + if (requested_format != CDROM_MSF && requested_format != CDROM_LBA) |
|---|
| 2668 | + return -EINVAL; |
|---|
| 2669 | + |
|---|
| 2670 | + /* make interface to low-level uniform */ |
|---|
| 2671 | + entry->cdte_format = CDROM_MSF; |
|---|
| 2672 | + ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, entry); |
|---|
| 2673 | + if (!ret) |
|---|
| 2674 | + sanitize_format(&entry->cdte_addr, &entry->cdte_format, |
|---|
| 2675 | + requested_format); |
|---|
| 2676 | + return ret; |
|---|
| 2677 | +} |
|---|
| 2678 | +EXPORT_SYMBOL_GPL(cdrom_read_tocentry); |
|---|
| 2679 | + |
|---|
| 2666 | 2680 | static int cdrom_ioctl_read_tocentry(struct cdrom_device_info *cdi, |
|---|
| 2667 | 2681 | void __user *argp) |
|---|
| 2668 | 2682 | { |
|---|
| 2669 | 2683 | struct cdrom_tocentry entry; |
|---|
| 2670 | | - u8 requested_format; |
|---|
| 2671 | 2684 | int ret; |
|---|
| 2672 | | - |
|---|
| 2673 | | - /* cd_dbg(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */ |
|---|
| 2674 | 2685 | |
|---|
| 2675 | 2686 | if (copy_from_user(&entry, argp, sizeof(entry))) |
|---|
| 2676 | 2687 | return -EFAULT; |
|---|
| 2677 | | - |
|---|
| 2678 | | - requested_format = entry.cdte_format; |
|---|
| 2679 | | - if (requested_format != CDROM_MSF && requested_format != CDROM_LBA) |
|---|
| 2680 | | - return -EINVAL; |
|---|
| 2681 | | - /* make interface to low-level uniform */ |
|---|
| 2682 | | - entry.cdte_format = CDROM_MSF; |
|---|
| 2683 | | - ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry); |
|---|
| 2684 | | - if (ret) |
|---|
| 2685 | | - return ret; |
|---|
| 2686 | | - sanitize_format(&entry.cdte_addr, &entry.cdte_format, requested_format); |
|---|
| 2687 | | - |
|---|
| 2688 | | - if (copy_to_user(argp, &entry, sizeof(entry))) |
|---|
| 2688 | + ret = cdrom_read_tocentry(cdi, &entry); |
|---|
| 2689 | + if (!ret && copy_to_user(argp, &entry, sizeof(entry))) |
|---|
| 2689 | 2690 | return -EFAULT; |
|---|
| 2690 | | - /* cd_dbg(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */ |
|---|
| 2691 | | - return 0; |
|---|
| 2691 | + return ret; |
|---|
| 2692 | 2692 | } |
|---|
| 2693 | 2693 | |
|---|
| 2694 | 2694 | static int cdrom_ioctl_play_msf(struct cdrom_device_info *cdi, |
|---|
| .. | .. |
|---|
| 3017 | 3017 | struct cdrom_read_audio ra; |
|---|
| 3018 | 3018 | int lba; |
|---|
| 3019 | 3019 | |
|---|
| 3020 | | - if (copy_from_user(&ra, (struct cdrom_read_audio __user *)arg, |
|---|
| 3021 | | - sizeof(ra))) |
|---|
| 3022 | | - return -EFAULT; |
|---|
| 3020 | +#ifdef CONFIG_COMPAT |
|---|
| 3021 | + if (in_compat_syscall()) { |
|---|
| 3022 | + struct compat_cdrom_read_audio { |
|---|
| 3023 | + union cdrom_addr addr; |
|---|
| 3024 | + u8 addr_format; |
|---|
| 3025 | + compat_int_t nframes; |
|---|
| 3026 | + compat_caddr_t buf; |
|---|
| 3027 | + } ra32; |
|---|
| 3028 | + |
|---|
| 3029 | + if (copy_from_user(&ra32, arg, sizeof(ra32))) |
|---|
| 3030 | + return -EFAULT; |
|---|
| 3031 | + |
|---|
| 3032 | + ra = (struct cdrom_read_audio) { |
|---|
| 3033 | + .addr = ra32.addr, |
|---|
| 3034 | + .addr_format = ra32.addr_format, |
|---|
| 3035 | + .nframes = ra32.nframes, |
|---|
| 3036 | + .buf = compat_ptr(ra32.buf), |
|---|
| 3037 | + }; |
|---|
| 3038 | + } else |
|---|
| 3039 | +#endif |
|---|
| 3040 | + { |
|---|
| 3041 | + if (copy_from_user(&ra, (struct cdrom_read_audio __user *)arg, |
|---|
| 3042 | + sizeof(ra))) |
|---|
| 3043 | + return -EFAULT; |
|---|
| 3044 | + } |
|---|
| 3023 | 3045 | |
|---|
| 3024 | 3046 | if (ra.addr_format == CDROM_MSF) |
|---|
| 3025 | 3047 | lba = msf_to_lba(ra.addr.msf.minute, |
|---|
| .. | .. |
|---|
| 3271 | 3293 | ret = cdrom_get_last_written(cdi, &last); |
|---|
| 3272 | 3294 | if (ret) |
|---|
| 3273 | 3295 | return ret; |
|---|
| 3274 | | - if (copy_to_user((long __user *)arg, &last, sizeof(last))) |
|---|
| 3275 | | - return -EFAULT; |
|---|
| 3276 | | - return 0; |
|---|
| 3296 | + if (in_compat_syscall()) |
|---|
| 3297 | + return put_user(last, (__s32 __user *)arg); |
|---|
| 3298 | + |
|---|
| 3299 | + return put_user(last, (long __user *)arg); |
|---|
| 3277 | 3300 | } |
|---|
| 3278 | 3301 | |
|---|
| 3279 | 3302 | static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, |
|---|
| .. | .. |
|---|
| 3424 | 3447 | EXPORT_SYMBOL(cdrom_open); |
|---|
| 3425 | 3448 | EXPORT_SYMBOL(cdrom_release); |
|---|
| 3426 | 3449 | EXPORT_SYMBOL(cdrom_ioctl); |
|---|
| 3427 | | -EXPORT_SYMBOL(cdrom_media_changed); |
|---|
| 3428 | 3450 | EXPORT_SYMBOL(cdrom_number_of_slots); |
|---|
| 3429 | 3451 | EXPORT_SYMBOL(cdrom_mode_select); |
|---|
| 3430 | 3452 | EXPORT_SYMBOL(cdrom_mode_sense); |
|---|
| .. | .. |
|---|
| 3495 | 3517 | } |
|---|
| 3496 | 3518 | |
|---|
| 3497 | 3519 | static int cdrom_sysctl_info(struct ctl_table *ctl, int write, |
|---|
| 3498 | | - void __user *buffer, size_t *lenp, loff_t *ppos) |
|---|
| 3520 | + void *buffer, size_t *lenp, loff_t *ppos) |
|---|
| 3499 | 3521 | { |
|---|
| 3500 | 3522 | int pos; |
|---|
| 3501 | 3523 | char *info = cdrom_sysctl_settings.info; |
|---|
| .. | .. |
|---|
| 3608 | 3630 | } |
|---|
| 3609 | 3631 | |
|---|
| 3610 | 3632 | static int cdrom_sysctl_handler(struct ctl_table *ctl, int write, |
|---|
| 3611 | | - void __user *buffer, size_t *lenp, loff_t *ppos) |
|---|
| 3633 | + void *buffer, size_t *lenp, loff_t *ppos) |
|---|
| 3612 | 3634 | { |
|---|
| 3613 | 3635 | int ret; |
|---|
| 3614 | 3636 | |
|---|