aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cdrom/cdrom.c
diff options
context:
space:
mode:
authorMarcin Slusarz <marcin.slusarz@gmail.com>2008-11-16 13:04:47 -0500
committerJens Axboe <jens.axboe@oracle.com>2008-12-29 02:28:42 -0500
commit3147c531b6b53fbbf8942689c4aa113c519f5e4e (patch)
tree7c3c615f6130a30e2916a0f3e1efb91e90487a04 /drivers/cdrom/cdrom.c
parent2b91bafcc0fc545e489e9537a38f487706960ea5 (diff)
cdrom: split mmc_ioctl to lower stack usage
Checkstack output: Before: mmc_ioctl: 584 After: mmc_ioctl_dvd_read_struct: 280 mmc_ioctl_cdrom_subchannel: 152 mmc_ioctl_cdrom_read_data: 120 mmc_ioctl_cdrom_volume: 104 mmc_ioctl_cdrom_read_audio: 104 (mmc_ioctl is inlined into cdrom_ioctl - 104 bytes) Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com> Cc: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Jens Axboe <jens.axboe@oracle.com> Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'drivers/cdrom/cdrom.c')
-rw-r--r--drivers/cdrom/cdrom.c570
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
2790static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, 2790static 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; 2843out:
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; 2848static 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
2872static 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!! */ 2895static 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); 2914static 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"); 2933static 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: 3004static 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: 3017static 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: { 3029static 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;
3055out:
3056 kfree(s);
3057 return ret;
3058}
3059
3060static 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: { 3076static 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: { 3089static 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); 3102static 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}