diff options
Diffstat (limited to 'drivers/cdrom')
-rw-r--r-- | drivers/cdrom/cdrom.c | 570 |
1 files changed, 329 insertions, 241 deletions
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 7d2e91cccb13..b927aa244247 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c | |||
@@ -2787,271 +2787,359 @@ static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size) | |||
2787 | return cdo->generic_packet(cdi, &cgc); | 2787 | return cdo->generic_packet(cdi, &cgc); |
2788 | } | 2788 | } |
2789 | 2789 | ||
2790 | static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, | 2790 | static noinline int mmc_ioctl_cdrom_read_data(struct cdrom_device_info *cdi, |
2791 | unsigned long arg) | 2791 | void __user *arg, |
2792 | { | 2792 | struct packet_command *cgc, |
2793 | struct cdrom_device_ops *cdo = cdi->ops; | 2793 | int cmd) |
2794 | struct packet_command cgc; | 2794 | { |
2795 | struct request_sense sense; | 2795 | struct request_sense sense; |
2796 | unsigned char buffer[32]; | 2796 | struct cdrom_msf msf; |
2797 | int ret = 0; | 2797 | int blocksize = 0, format = 0, lba; |
2798 | 2798 | int ret; | |
2799 | memset(&cgc, 0, sizeof(cgc)); | ||
2800 | 2799 | ||
2801 | /* build a unified command and queue it through | ||
2802 | cdo->generic_packet() */ | ||
2803 | switch (cmd) { | 2800 | switch (cmd) { |
2804 | case CDROMREADRAW: | 2801 | case CDROMREADRAW: |
2802 | blocksize = CD_FRAMESIZE_RAW; | ||
2803 | break; | ||
2805 | case CDROMREADMODE1: | 2804 | case CDROMREADMODE1: |
2806 | case CDROMREADMODE2: { | 2805 | blocksize = CD_FRAMESIZE; |
2807 | struct cdrom_msf msf; | 2806 | format = 2; |
2808 | int blocksize = 0, format = 0, lba; | 2807 | break; |
2809 | 2808 | case CDROMREADMODE2: | |
2810 | switch (cmd) { | 2809 | blocksize = CD_FRAMESIZE_RAW0; |
2811 | case CDROMREADRAW: | 2810 | break; |
2812 | blocksize = CD_FRAMESIZE_RAW; | 2811 | } |
2813 | break; | 2812 | IOCTL_IN(arg, struct cdrom_msf, msf); |
2814 | case CDROMREADMODE1: | 2813 | lba = msf_to_lba(msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0); |
2815 | blocksize = CD_FRAMESIZE; | 2814 | /* FIXME: we need upper bound checking, too!! */ |
2816 | format = 2; | 2815 | if (lba < 0) |
2817 | break; | 2816 | return -EINVAL; |
2818 | case CDROMREADMODE2: | 2817 | |
2819 | blocksize = CD_FRAMESIZE_RAW0; | 2818 | cgc->buffer = kmalloc(blocksize, GFP_KERNEL); |
2820 | break; | 2819 | if (cgc->buffer == NULL) |
2821 | } | 2820 | return -ENOMEM; |
2822 | IOCTL_IN(arg, struct cdrom_msf, msf); | 2821 | |
2823 | lba = msf_to_lba(msf.cdmsf_min0,msf.cdmsf_sec0,msf.cdmsf_frame0); | 2822 | memset(&sense, 0, sizeof(sense)); |
2824 | /* FIXME: we need upper bound checking, too!! */ | 2823 | cgc->sense = &sense; |
2825 | if (lba < 0) | 2824 | cgc->data_direction = CGC_DATA_READ; |
2826 | return -EINVAL; | 2825 | ret = cdrom_read_block(cdi, cgc, lba, 1, format, blocksize); |
2827 | cgc.buffer = kmalloc(blocksize, GFP_KERNEL); | 2826 | if (ret && sense.sense_key == 0x05 && |
2828 | if (cgc.buffer == NULL) | 2827 | sense.asc == 0x20 && |
2829 | return -ENOMEM; | 2828 | sense.ascq == 0x00) { |
2830 | memset(&sense, 0, sizeof(sense)); | 2829 | /* |
2831 | cgc.sense = &sense; | 2830 | * SCSI-II devices are not required to support |
2832 | cgc.data_direction = CGC_DATA_READ; | 2831 | * READ_CD, so let's try switching block size |
2833 | ret = cdrom_read_block(cdi, &cgc, lba, 1, format, blocksize); | 2832 | */ |
2834 | if (ret && sense.sense_key==0x05 && sense.asc==0x20 && sense.ascq==0x00) { | 2833 | /* FIXME: switch back again... */ |
2835 | /* | 2834 | ret = cdrom_switch_blocksize(cdi, blocksize); |
2836 | * SCSI-II devices are not required to support | 2835 | if (ret) |
2837 | * READ_CD, so let's try switching block size | 2836 | goto out; |
2838 | */ | 2837 | cgc->sense = NULL; |
2839 | /* FIXME: switch back again... */ | 2838 | ret = cdrom_read_cd(cdi, cgc, lba, blocksize, 1); |
2840 | if ((ret = cdrom_switch_blocksize(cdi, blocksize))) { | 2839 | ret |= cdrom_switch_blocksize(cdi, blocksize); |
2841 | kfree(cgc.buffer); | 2840 | } |
2842 | return ret; | 2841 | if (!ret && copy_to_user(arg, cgc->buffer, blocksize)) |
2843 | } | 2842 | ret = -EFAULT; |
2844 | cgc.sense = NULL; | 2843 | out: |
2845 | ret = cdrom_read_cd(cdi, &cgc, lba, blocksize, 1); | 2844 | kfree(cgc->buffer); |
2846 | ret |= cdrom_switch_blocksize(cdi, blocksize); | 2845 | return ret; |
2847 | } | 2846 | } |
2848 | if (!ret && copy_to_user((char __user *)arg, cgc.buffer, blocksize)) | 2847 | |
2849 | ret = -EFAULT; | 2848 | static noinline int mmc_ioctl_cdrom_read_audio(struct cdrom_device_info *cdi, |
2850 | kfree(cgc.buffer); | 2849 | void __user *arg) |
2850 | { | ||
2851 | struct cdrom_read_audio ra; | ||
2852 | int lba; | ||
2853 | |||
2854 | IOCTL_IN(arg, struct cdrom_read_audio, ra); | ||
2855 | |||
2856 | if (ra.addr_format == CDROM_MSF) | ||
2857 | lba = msf_to_lba(ra.addr.msf.minute, | ||
2858 | ra.addr.msf.second, | ||
2859 | ra.addr.msf.frame); | ||
2860 | else if (ra.addr_format == CDROM_LBA) | ||
2861 | lba = ra.addr.lba; | ||
2862 | else | ||
2863 | return -EINVAL; | ||
2864 | |||
2865 | /* FIXME: we need upper bound checking, too!! */ | ||
2866 | if (lba < 0 || ra.nframes <= 0 || ra.nframes > CD_FRAMES) | ||
2867 | return -EINVAL; | ||
2868 | |||
2869 | return cdrom_read_cdda(cdi, ra.buf, lba, ra.nframes); | ||
2870 | } | ||
2871 | |||
2872 | static noinline int mmc_ioctl_cdrom_subchannel(struct cdrom_device_info *cdi, | ||
2873 | void __user *arg) | ||
2874 | { | ||
2875 | int ret; | ||
2876 | struct cdrom_subchnl q; | ||
2877 | u_char requested, back; | ||
2878 | IOCTL_IN(arg, struct cdrom_subchnl, q); | ||
2879 | requested = q.cdsc_format; | ||
2880 | if (!((requested == CDROM_MSF) || | ||
2881 | (requested == CDROM_LBA))) | ||
2882 | return -EINVAL; | ||
2883 | q.cdsc_format = CDROM_MSF; | ||
2884 | ret = cdrom_read_subchannel(cdi, &q, 0); | ||
2885 | if (ret) | ||
2851 | return ret; | 2886 | return ret; |
2852 | } | 2887 | back = q.cdsc_format; /* local copy */ |
2853 | case CDROMREADAUDIO: { | 2888 | sanitize_format(&q.cdsc_absaddr, &back, requested); |
2854 | struct cdrom_read_audio ra; | 2889 | sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); |
2855 | int lba; | 2890 | IOCTL_OUT(arg, struct cdrom_subchnl, q); |
2856 | 2891 | /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ | |
2857 | IOCTL_IN(arg, struct cdrom_read_audio, ra); | 2892 | return 0; |
2858 | 2893 | } | |
2859 | if (ra.addr_format == CDROM_MSF) | ||
2860 | lba = msf_to_lba(ra.addr.msf.minute, | ||
2861 | ra.addr.msf.second, | ||
2862 | ra.addr.msf.frame); | ||
2863 | else if (ra.addr_format == CDROM_LBA) | ||
2864 | lba = ra.addr.lba; | ||
2865 | else | ||
2866 | return -EINVAL; | ||
2867 | 2894 | ||
2868 | /* FIXME: we need upper bound checking, too!! */ | 2895 | static noinline int mmc_ioctl_cdrom_play_msf(struct cdrom_device_info *cdi, |
2869 | if (lba < 0 || ra.nframes <= 0 || ra.nframes > CD_FRAMES) | 2896 | void __user *arg, |
2870 | return -EINVAL; | 2897 | struct packet_command *cgc) |
2898 | { | ||
2899 | struct cdrom_device_ops *cdo = cdi->ops; | ||
2900 | struct cdrom_msf msf; | ||
2901 | cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); | ||
2902 | IOCTL_IN(arg, struct cdrom_msf, msf); | ||
2903 | cgc->cmd[0] = GPCMD_PLAY_AUDIO_MSF; | ||
2904 | cgc->cmd[3] = msf.cdmsf_min0; | ||
2905 | cgc->cmd[4] = msf.cdmsf_sec0; | ||
2906 | cgc->cmd[5] = msf.cdmsf_frame0; | ||
2907 | cgc->cmd[6] = msf.cdmsf_min1; | ||
2908 | cgc->cmd[7] = msf.cdmsf_sec1; | ||
2909 | cgc->cmd[8] = msf.cdmsf_frame1; | ||
2910 | cgc->data_direction = CGC_DATA_NONE; | ||
2911 | return cdo->generic_packet(cdi, cgc); | ||
2912 | } | ||
2871 | 2913 | ||
2872 | return cdrom_read_cdda(cdi, ra.buf, lba, ra.nframes); | 2914 | static noinline int mmc_ioctl_cdrom_play_blk(struct cdrom_device_info *cdi, |
2873 | } | 2915 | void __user *arg, |
2874 | case CDROMSUBCHNL: { | 2916 | struct packet_command *cgc) |
2875 | struct cdrom_subchnl q; | 2917 | { |
2876 | u_char requested, back; | 2918 | struct cdrom_device_ops *cdo = cdi->ops; |
2877 | IOCTL_IN(arg, struct cdrom_subchnl, q); | 2919 | struct cdrom_blk blk; |
2878 | requested = q.cdsc_format; | 2920 | cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLK\n"); |
2879 | if (!((requested == CDROM_MSF) || | 2921 | IOCTL_IN(arg, struct cdrom_blk, blk); |
2880 | (requested == CDROM_LBA))) | 2922 | cgc->cmd[0] = GPCMD_PLAY_AUDIO_10; |
2881 | return -EINVAL; | 2923 | cgc->cmd[2] = (blk.from >> 24) & 0xff; |
2882 | q.cdsc_format = CDROM_MSF; | 2924 | cgc->cmd[3] = (blk.from >> 16) & 0xff; |
2883 | if ((ret = cdrom_read_subchannel(cdi, &q, 0))) | 2925 | cgc->cmd[4] = (blk.from >> 8) & 0xff; |
2884 | return ret; | 2926 | cgc->cmd[5] = blk.from & 0xff; |
2885 | back = q.cdsc_format; /* local copy */ | 2927 | cgc->cmd[7] = (blk.len >> 8) & 0xff; |
2886 | sanitize_format(&q.cdsc_absaddr, &back, requested); | 2928 | cgc->cmd[8] = blk.len & 0xff; |
2887 | sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested); | 2929 | cgc->data_direction = CGC_DATA_NONE; |
2888 | IOCTL_OUT(arg, struct cdrom_subchnl, q); | 2930 | return cdo->generic_packet(cdi, cgc); |
2889 | /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */ | 2931 | } |
2890 | return 0; | ||
2891 | } | ||
2892 | case CDROMPLAYMSF: { | ||
2893 | struct cdrom_msf msf; | ||
2894 | cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n"); | ||
2895 | IOCTL_IN(arg, struct cdrom_msf, msf); | ||
2896 | cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF; | ||
2897 | cgc.cmd[3] = msf.cdmsf_min0; | ||
2898 | cgc.cmd[4] = msf.cdmsf_sec0; | ||
2899 | cgc.cmd[5] = msf.cdmsf_frame0; | ||
2900 | cgc.cmd[6] = msf.cdmsf_min1; | ||
2901 | cgc.cmd[7] = msf.cdmsf_sec1; | ||
2902 | cgc.cmd[8] = msf.cdmsf_frame1; | ||
2903 | cgc.data_direction = CGC_DATA_NONE; | ||
2904 | return cdo->generic_packet(cdi, &cgc); | ||
2905 | } | ||
2906 | case CDROMPLAYBLK: { | ||
2907 | struct cdrom_blk blk; | ||
2908 | cdinfo(CD_DO_IOCTL, "entering CDROMPLAYBLK\n"); | ||
2909 | IOCTL_IN(arg, struct cdrom_blk, blk); | ||
2910 | cgc.cmd[0] = GPCMD_PLAY_AUDIO_10; | ||
2911 | cgc.cmd[2] = (blk.from >> 24) & 0xff; | ||
2912 | cgc.cmd[3] = (blk.from >> 16) & 0xff; | ||
2913 | cgc.cmd[4] = (blk.from >> 8) & 0xff; | ||
2914 | cgc.cmd[5] = blk.from & 0xff; | ||
2915 | cgc.cmd[7] = (blk.len >> 8) & 0xff; | ||
2916 | cgc.cmd[8] = blk.len & 0xff; | ||
2917 | cgc.data_direction = CGC_DATA_NONE; | ||
2918 | return cdo->generic_packet(cdi, &cgc); | ||
2919 | } | ||
2920 | case CDROMVOLCTRL: | ||
2921 | case CDROMVOLREAD: { | ||
2922 | struct cdrom_volctrl volctrl; | ||
2923 | char mask[sizeof(buffer)]; | ||
2924 | unsigned short offset; | ||
2925 | 2932 | ||
2926 | cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n"); | 2933 | static noinline int mmc_ioctl_cdrom_volume(struct cdrom_device_info *cdi, |
2934 | void __user *arg, | ||
2935 | struct packet_command *cgc, | ||
2936 | unsigned int cmd) | ||
2937 | { | ||
2938 | struct cdrom_volctrl volctrl; | ||
2939 | unsigned char buffer[32]; | ||
2940 | char mask[sizeof(buffer)]; | ||
2941 | unsigned short offset; | ||
2942 | int ret; | ||
2943 | |||
2944 | cdinfo(CD_DO_IOCTL, "entering CDROMVOLUME\n"); | ||
2927 | 2945 | ||
2928 | IOCTL_IN(arg, struct cdrom_volctrl, volctrl); | 2946 | IOCTL_IN(arg, struct cdrom_volctrl, volctrl); |
2929 | 2947 | ||
2930 | cgc.buffer = buffer; | 2948 | cgc->buffer = buffer; |
2931 | cgc.buflen = 24; | 2949 | cgc->buflen = 24; |
2932 | if ((ret = cdrom_mode_sense(cdi, &cgc, GPMODE_AUDIO_CTL_PAGE, 0))) | 2950 | ret = cdrom_mode_sense(cdi, cgc, GPMODE_AUDIO_CTL_PAGE, 0); |
2933 | return ret; | 2951 | if (ret) |
2952 | return ret; | ||
2934 | 2953 | ||
2935 | /* originally the code depended on buffer[1] to determine | 2954 | /* originally the code depended on buffer[1] to determine |
2936 | how much data is available for transfer. buffer[1] is | 2955 | how much data is available for transfer. buffer[1] is |
2937 | unfortunately ambigious and the only reliable way seem | 2956 | unfortunately ambigious and the only reliable way seem |
2938 | to be to simply skip over the block descriptor... */ | 2957 | to be to simply skip over the block descriptor... */ |
2939 | offset = 8 + be16_to_cpu(*(__be16 *)(buffer+6)); | 2958 | offset = 8 + be16_to_cpu(*(__be16 *)(buffer + 6)); |
2940 | 2959 | ||
2941 | if (offset + 16 > sizeof(buffer)) | 2960 | if (offset + 16 > sizeof(buffer)) |
2942 | return -E2BIG; | 2961 | return -E2BIG; |
2943 | 2962 | ||
2944 | if (offset + 16 > cgc.buflen) { | 2963 | if (offset + 16 > cgc->buflen) { |
2945 | cgc.buflen = offset+16; | 2964 | cgc->buflen = offset + 16; |
2946 | ret = cdrom_mode_sense(cdi, &cgc, | 2965 | ret = cdrom_mode_sense(cdi, cgc, |
2947 | GPMODE_AUDIO_CTL_PAGE, 0); | 2966 | GPMODE_AUDIO_CTL_PAGE, 0); |
2948 | if (ret) | 2967 | if (ret) |
2949 | return ret; | 2968 | return ret; |
2950 | } | 2969 | } |
2951 | 2970 | ||
2952 | /* sanity check */ | 2971 | /* sanity check */ |
2953 | if ((buffer[offset] & 0x3f) != GPMODE_AUDIO_CTL_PAGE || | 2972 | if ((buffer[offset] & 0x3f) != GPMODE_AUDIO_CTL_PAGE || |
2954 | buffer[offset+1] < 14) | 2973 | buffer[offset + 1] < 14) |
2955 | return -EINVAL; | 2974 | return -EINVAL; |
2956 | 2975 | ||
2957 | /* now we have the current volume settings. if it was only | 2976 | /* now we have the current volume settings. if it was only |
2958 | a CDROMVOLREAD, return these values */ | 2977 | a CDROMVOLREAD, return these values */ |
2959 | if (cmd == CDROMVOLREAD) { | 2978 | if (cmd == CDROMVOLREAD) { |
2960 | volctrl.channel0 = buffer[offset+9]; | 2979 | volctrl.channel0 = buffer[offset+9]; |
2961 | volctrl.channel1 = buffer[offset+11]; | 2980 | volctrl.channel1 = buffer[offset+11]; |
2962 | volctrl.channel2 = buffer[offset+13]; | 2981 | volctrl.channel2 = buffer[offset+13]; |
2963 | volctrl.channel3 = buffer[offset+15]; | 2982 | volctrl.channel3 = buffer[offset+15]; |
2964 | IOCTL_OUT(arg, struct cdrom_volctrl, volctrl); | 2983 | IOCTL_OUT(arg, struct cdrom_volctrl, volctrl); |
2965 | return 0; | 2984 | return 0; |
2966 | } | 2985 | } |
2967 | 2986 | ||
2968 | /* get the volume mask */ | 2987 | /* get the volume mask */ |
2969 | cgc.buffer = mask; | 2988 | cgc->buffer = mask; |
2970 | if ((ret = cdrom_mode_sense(cdi, &cgc, | 2989 | ret = cdrom_mode_sense(cdi, cgc, GPMODE_AUDIO_CTL_PAGE, 1); |
2971 | GPMODE_AUDIO_CTL_PAGE, 1))) | 2990 | if (ret) |
2972 | return ret; | 2991 | return ret; |
2973 | 2992 | ||
2974 | buffer[offset+9] = volctrl.channel0 & mask[offset+9]; | 2993 | buffer[offset + 9] = volctrl.channel0 & mask[offset + 9]; |
2975 | buffer[offset+11] = volctrl.channel1 & mask[offset+11]; | 2994 | buffer[offset + 11] = volctrl.channel1 & mask[offset + 11]; |
2976 | buffer[offset+13] = volctrl.channel2 & mask[offset+13]; | 2995 | buffer[offset + 13] = volctrl.channel2 & mask[offset + 13]; |
2977 | buffer[offset+15] = volctrl.channel3 & mask[offset+15]; | 2996 | buffer[offset + 15] = volctrl.channel3 & mask[offset + 15]; |
2978 | 2997 | ||
2979 | /* set volume */ | 2998 | /* set volume */ |
2980 | cgc.buffer = buffer + offset - 8; | 2999 | cgc->buffer = buffer + offset - 8; |
2981 | memset(cgc.buffer, 0, 8); | 3000 | memset(cgc->buffer, 0, 8); |
2982 | return cdrom_mode_select(cdi, &cgc); | 3001 | return cdrom_mode_select(cdi, cgc); |
2983 | } | 3002 | } |
2984 | 3003 | ||
2985 | case CDROMSTART: | 3004 | static noinline int mmc_ioctl_cdrom_start_stop(struct cdrom_device_info *cdi, |
2986 | case CDROMSTOP: { | 3005 | struct packet_command *cgc, |
2987 | cdinfo(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOP\n"); | 3006 | int cmd) |
2988 | cgc.cmd[0] = GPCMD_START_STOP_UNIT; | 3007 | { |
2989 | cgc.cmd[1] = 1; | 3008 | struct cdrom_device_ops *cdo = cdi->ops; |
2990 | cgc.cmd[4] = (cmd == CDROMSTART) ? 1 : 0; | 3009 | cdinfo(CD_DO_IOCTL, "entering CDROMSTART/CDROMSTOP\n"); |
2991 | cgc.data_direction = CGC_DATA_NONE; | 3010 | cgc->cmd[0] = GPCMD_START_STOP_UNIT; |
2992 | return cdo->generic_packet(cdi, &cgc); | 3011 | cgc->cmd[1] = 1; |
2993 | } | 3012 | cgc->cmd[4] = (cmd == CDROMSTART) ? 1 : 0; |
3013 | cgc->data_direction = CGC_DATA_NONE; | ||
3014 | return cdo->generic_packet(cdi, cgc); | ||
3015 | } | ||
2994 | 3016 | ||
2995 | case CDROMPAUSE: | 3017 | static noinline int mmc_ioctl_cdrom_pause_resume(struct cdrom_device_info *cdi, |
2996 | case CDROMRESUME: { | 3018 | struct packet_command *cgc, |
2997 | cdinfo(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n"); | 3019 | int cmd) |
2998 | cgc.cmd[0] = GPCMD_PAUSE_RESUME; | 3020 | { |
2999 | cgc.cmd[8] = (cmd == CDROMRESUME) ? 1 : 0; | 3021 | struct cdrom_device_ops *cdo = cdi->ops; |
3000 | cgc.data_direction = CGC_DATA_NONE; | 3022 | cdinfo(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n"); |
3001 | return cdo->generic_packet(cdi, &cgc); | 3023 | cgc->cmd[0] = GPCMD_PAUSE_RESUME; |
3002 | } | 3024 | cgc->cmd[8] = (cmd == CDROMRESUME) ? 1 : 0; |
3025 | cgc->data_direction = CGC_DATA_NONE; | ||
3026 | return cdo->generic_packet(cdi, cgc); | ||
3027 | } | ||
3003 | 3028 | ||
3004 | case DVD_READ_STRUCT: { | 3029 | static noinline int mmc_ioctl_dvd_read_struct(struct cdrom_device_info *cdi, |
3005 | dvd_struct *s; | 3030 | void __user *arg) |
3006 | int size = sizeof(dvd_struct); | 3031 | { |
3007 | if (!CDROM_CAN(CDC_DVD)) | 3032 | int ret; |
3008 | return -ENOSYS; | 3033 | dvd_struct *s; |
3009 | if ((s = kmalloc(size, GFP_KERNEL)) == NULL) | 3034 | int size = sizeof(dvd_struct); |
3010 | return -ENOMEM; | 3035 | |
3011 | cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n"); | 3036 | if (!CDROM_CAN(CDC_DVD)) |
3012 | if (copy_from_user(s, (dvd_struct __user *)arg, size)) { | 3037 | return -ENOSYS; |
3013 | kfree(s); | 3038 | |
3014 | return -EFAULT; | 3039 | s = kmalloc(size, GFP_KERNEL); |
3015 | } | 3040 | if (!s) |
3016 | if ((ret = dvd_read_struct(cdi, s))) { | 3041 | return -ENOMEM; |
3017 | kfree(s); | 3042 | |
3018 | return ret; | 3043 | cdinfo(CD_DO_IOCTL, "entering DVD_READ_STRUCT\n"); |
3019 | } | 3044 | if (copy_from_user(s, arg, size)) { |
3020 | if (copy_to_user((dvd_struct __user *)arg, s, size)) | ||
3021 | ret = -EFAULT; | ||
3022 | kfree(s); | 3045 | kfree(s); |
3046 | return -EFAULT; | ||
3047 | } | ||
3048 | |||
3049 | ret = dvd_read_struct(cdi, s); | ||
3050 | if (ret) | ||
3051 | goto out; | ||
3052 | |||
3053 | if (copy_to_user(arg, s, size)) | ||
3054 | ret = -EFAULT; | ||
3055 | out: | ||
3056 | kfree(s); | ||
3057 | return ret; | ||
3058 | } | ||
3059 | |||
3060 | static noinline int mmc_ioctl_dvd_auth(struct cdrom_device_info *cdi, | ||
3061 | void __user *arg) | ||
3062 | { | ||
3063 | int ret; | ||
3064 | dvd_authinfo ai; | ||
3065 | if (!CDROM_CAN(CDC_DVD)) | ||
3066 | return -ENOSYS; | ||
3067 | cdinfo(CD_DO_IOCTL, "entering DVD_AUTH\n"); | ||
3068 | IOCTL_IN(arg, dvd_authinfo, ai); | ||
3069 | ret = dvd_do_auth(cdi, &ai); | ||
3070 | if (ret) | ||
3023 | return ret; | 3071 | return ret; |
3024 | } | 3072 | IOCTL_OUT(arg, dvd_authinfo, ai); |
3073 | return 0; | ||
3074 | } | ||
3025 | 3075 | ||
3026 | case DVD_AUTH: { | 3076 | static noinline int mmc_ioctl_cdrom_next_writable(struct cdrom_device_info *cdi, |
3027 | dvd_authinfo ai; | 3077 | void __user *arg) |
3028 | if (!CDROM_CAN(CDC_DVD)) | 3078 | { |
3029 | return -ENOSYS; | 3079 | int ret; |
3030 | cdinfo(CD_DO_IOCTL, "entering DVD_AUTH\n"); | 3080 | long next = 0; |
3031 | IOCTL_IN(arg, dvd_authinfo, ai); | 3081 | cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n"); |
3032 | if ((ret = dvd_do_auth (cdi, &ai))) | 3082 | ret = cdrom_get_next_writable(cdi, &next); |
3033 | return ret; | 3083 | if (ret) |
3034 | IOCTL_OUT(arg, dvd_authinfo, ai); | 3084 | return ret; |
3035 | return 0; | 3085 | IOCTL_OUT(arg, long, next); |
3036 | } | 3086 | return 0; |
3087 | } | ||
3037 | 3088 | ||
3038 | case CDROM_NEXT_WRITABLE: { | 3089 | static noinline int mmc_ioctl_cdrom_last_written(struct cdrom_device_info *cdi, |
3039 | long next = 0; | 3090 | void __user *arg) |
3040 | cdinfo(CD_DO_IOCTL, "entering CDROM_NEXT_WRITABLE\n"); | 3091 | { |
3041 | if ((ret = cdrom_get_next_writable(cdi, &next))) | 3092 | int ret; |
3042 | return ret; | 3093 | long last = 0; |
3043 | IOCTL_OUT(arg, long, next); | 3094 | cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n"); |
3044 | return 0; | 3095 | ret = cdrom_get_last_written(cdi, &last); |
3045 | } | 3096 | if (ret) |
3046 | case CDROM_LAST_WRITTEN: { | 3097 | return ret; |
3047 | long last = 0; | 3098 | IOCTL_OUT(arg, long, last); |
3048 | cdinfo(CD_DO_IOCTL, "entering CDROM_LAST_WRITTEN\n"); | 3099 | return 0; |
3049 | if ((ret = cdrom_get_last_written(cdi, &last))) | 3100 | } |
3050 | return ret; | 3101 | |
3051 | IOCTL_OUT(arg, long, last); | 3102 | static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, |
3052 | return 0; | 3103 | unsigned long arg) |
3053 | } | 3104 | { |
3054 | } /* switch */ | 3105 | struct packet_command cgc; |
3106 | void __user *userptr = (void __user *)arg; | ||
3107 | |||
3108 | memset(&cgc, 0, sizeof(cgc)); | ||
3109 | |||
3110 | /* build a unified command and queue it through | ||
3111 | cdo->generic_packet() */ | ||
3112 | switch (cmd) { | ||
3113 | case CDROMREADRAW: | ||
3114 | case CDROMREADMODE1: | ||
3115 | case CDROMREADMODE2: | ||
3116 | return mmc_ioctl_cdrom_read_data(cdi, userptr, &cgc, cmd); | ||
3117 | case CDROMREADAUDIO: | ||
3118 | return mmc_ioctl_cdrom_read_audio(cdi, userptr); | ||
3119 | case CDROMSUBCHNL: | ||
3120 | return mmc_ioctl_cdrom_subchannel(cdi, userptr); | ||
3121 | case CDROMPLAYMSF: | ||
3122 | return mmc_ioctl_cdrom_play_msf(cdi, userptr, &cgc); | ||
3123 | case CDROMPLAYBLK: | ||
3124 | return mmc_ioctl_cdrom_play_blk(cdi, userptr, &cgc); | ||
3125 | case CDROMVOLCTRL: | ||
3126 | case CDROMVOLREAD: | ||
3127 | return mmc_ioctl_cdrom_volume(cdi, userptr, &cgc, cmd); | ||
3128 | case CDROMSTART: | ||
3129 | case CDROMSTOP: | ||
3130 | return mmc_ioctl_cdrom_start_stop(cdi, &cgc, cmd); | ||
3131 | case CDROMPAUSE: | ||
3132 | case CDROMRESUME: | ||
3133 | return mmc_ioctl_cdrom_pause_resume(cdi, &cgc, cmd); | ||
3134 | case DVD_READ_STRUCT: | ||
3135 | return mmc_ioctl_dvd_read_struct(cdi, userptr); | ||
3136 | case DVD_AUTH: | ||
3137 | return mmc_ioctl_dvd_auth(cdi, userptr); | ||
3138 | case CDROM_NEXT_WRITABLE: | ||
3139 | return mmc_ioctl_cdrom_next_writable(cdi, userptr); | ||
3140 | case CDROM_LAST_WRITTEN: | ||
3141 | return mmc_ioctl_cdrom_last_written(cdi, userptr); | ||
3142 | } | ||
3055 | 3143 | ||
3056 | return -ENOTTY; | 3144 | return -ENOTTY; |
3057 | } | 3145 | } |