aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cdrom/cdrom.c
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@hera.kernel.org>2006-03-23 12:05:47 -0500
committerAnton Altaparmakov <aia21@hera.kernel.org>2006-03-23 12:05:47 -0500
commita05ba4561fa3ad8b64a27577d0d38c190f60f762 (patch)
tree5eb7561113e006b7bad0bef50dec6821962b1b36 /drivers/cdrom/cdrom.c
parent74293759002aa7db0179158c20676a034614577b (diff)
parentb0e6e962992b76580f4900b166a337bad7c1e81b (diff)
Merge branch 'master' of /home/aia21/ntfs-2.6/
Diffstat (limited to 'drivers/cdrom/cdrom.c')
-rw-r--r--drivers/cdrom/cdrom.c874
1 files changed, 532 insertions, 342 deletions
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 879bbc26ce96..a59876a0bfa1 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -407,7 +407,6 @@ int register_cdrom(struct cdrom_device_info *cdi)
407 ENSURE(get_mcn, CDC_MCN); 407 ENSURE(get_mcn, CDC_MCN);
408 ENSURE(reset, CDC_RESET); 408 ENSURE(reset, CDC_RESET);
409 ENSURE(audio_ioctl, CDC_PLAY_AUDIO); 409 ENSURE(audio_ioctl, CDC_PLAY_AUDIO);
410 ENSURE(dev_ioctl, CDC_IOCTLS);
411 ENSURE(generic_packet, CDC_GENERIC_PACKET); 410 ENSURE(generic_packet, CDC_GENERIC_PACKET);
412 cdi->mc_flags = 0; 411 cdi->mc_flags = 0;
413 cdo->n_minors = 0; 412 cdo->n_minors = 0;
@@ -2196,395 +2195,586 @@ retry:
2196 return cdrom_read_cdda_old(cdi, ubuf, lba, nframes); 2195 return cdrom_read_cdda_old(cdi, ubuf, lba, nframes);
2197} 2196}
2198 2197
2199/* Just about every imaginable ioctl is supported in the Uniform layer 2198static int cdrom_ioctl_multisession(struct cdrom_device_info *cdi,
2200 * these days. ATAPI / SCSI specific code now mainly resides in 2199 void __user *argp)
2201 * mmc_ioct().
2202 */
2203int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
2204 struct inode *ip, unsigned int cmd, unsigned long arg)
2205{ 2200{
2206 struct cdrom_device_ops *cdo = cdi->ops; 2201 struct cdrom_multisession ms_info;
2202 u8 requested_format;
2207 int ret; 2203 int ret;
2208 2204
2209 /* Try the generic SCSI command ioctl's first.. */ 2205 cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n");
2210 ret = scsi_cmd_ioctl(file, ip->i_bdev->bd_disk, cmd, (void __user *)arg); 2206
2211 if (ret != -ENOTTY) 2207 if (!(cdi->ops->capability & CDC_MULTI_SESSION))
2208 return -ENOSYS;
2209
2210 if (copy_from_user(&ms_info, argp, sizeof(ms_info)))
2211 return -EFAULT;
2212
2213 requested_format = ms_info.addr_format;
2214 if (requested_format != CDROM_MSF && requested_format != CDROM_LBA)
2215 return -EINVAL;
2216 ms_info.addr_format = CDROM_LBA;
2217
2218 ret = cdi->ops->get_last_session(cdi, &ms_info);
2219 if (ret)
2212 return ret; 2220 return ret;
2213 2221
2214 /* the first few commands do not deal with audio drive_info, but 2222 sanitize_format(&ms_info.addr, &ms_info.addr_format, requested_format);
2215 only with routines in cdrom device operations. */ 2223
2216 switch (cmd) { 2224 if (copy_to_user(argp, &ms_info, sizeof(ms_info)))
2217 case CDROMMULTISESSION: { 2225 return -EFAULT;
2218 struct cdrom_multisession ms_info; 2226
2219 u_char requested_format; 2227 cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n");
2220 cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n"); 2228 return 0;
2221 if (!(cdo->capability & CDC_MULTI_SESSION)) 2229}
2222 return -ENOSYS; 2230
2223 IOCTL_IN(arg, struct cdrom_multisession, ms_info); 2231static int cdrom_ioctl_eject(struct cdrom_device_info *cdi)
2224 requested_format = ms_info.addr_format; 2232{
2225 if (!((requested_format == CDROM_MSF) || 2233 cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n");
2226 (requested_format == CDROM_LBA))) 2234
2227 return -EINVAL; 2235 if (!CDROM_CAN(CDC_OPEN_TRAY))
2228 ms_info.addr_format = CDROM_LBA; 2236 return -ENOSYS;
2229 if ((ret=cdo->get_last_session(cdi, &ms_info))) 2237 if (cdi->use_count != 1 || keeplocked)
2238 return -EBUSY;
2239 if (CDROM_CAN(CDC_LOCK)) {
2240 int ret = cdi->ops->lock_door(cdi, 0);
2241 if (ret)
2230 return ret; 2242 return ret;
2231 sanitize_format(&ms_info.addr, &ms_info.addr_format, 2243 }
2232 requested_format);
2233 IOCTL_OUT(arg, struct cdrom_multisession, ms_info);
2234 cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n");
2235 return 0;
2236 }
2237 2244
2238 case CDROMEJECT: { 2245 return cdi->ops->tray_move(cdi, 1);
2239 cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n"); 2246}
2240 if (!CDROM_CAN(CDC_OPEN_TRAY))
2241 return -ENOSYS;
2242 if (cdi->use_count != 1 || keeplocked)
2243 return -EBUSY;
2244 if (CDROM_CAN(CDC_LOCK))
2245 if ((ret=cdo->lock_door(cdi, 0)))
2246 return ret;
2247 2247
2248 return cdo->tray_move(cdi, 1); 2248static int cdrom_ioctl_closetray(struct cdrom_device_info *cdi)
2249 } 2249{
2250 cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n");
2250 2251
2251 case CDROMCLOSETRAY: { 2252 if (!CDROM_CAN(CDC_CLOSE_TRAY))
2252 cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n"); 2253 return -ENOSYS;
2253 if (!CDROM_CAN(CDC_CLOSE_TRAY)) 2254 return cdi->ops->tray_move(cdi, 0);
2254 return -ENOSYS; 2255}
2255 return cdo->tray_move(cdi, 0);
2256 }
2257 2256
2258 case CDROMEJECT_SW: { 2257static int cdrom_ioctl_eject_sw(struct cdrom_device_info *cdi,
2259 cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n"); 2258 unsigned long arg)
2260 if (!CDROM_CAN(CDC_OPEN_TRAY)) 2259{
2261 return -ENOSYS; 2260 cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n");
2262 if (keeplocked)
2263 return -EBUSY;
2264 cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT);
2265 if (arg)
2266 cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT;
2267 return 0;
2268 }
2269 2261
2270 case CDROM_MEDIA_CHANGED: { 2262 if (!CDROM_CAN(CDC_OPEN_TRAY))
2271 struct cdrom_changer_info *info; 2263 return -ENOSYS;
2272 int changed; 2264 if (keeplocked)
2265 return -EBUSY;
2273 2266
2274 cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n"); 2267 cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT);
2275 if (!CDROM_CAN(CDC_MEDIA_CHANGED)) 2268 if (arg)
2276 return -ENOSYS; 2269 cdi->options |= CDO_AUTO_CLOSE | CDO_AUTO_EJECT;
2270 return 0;
2271}
2277 2272
2278 /* cannot select disc or select current disc */ 2273static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi,
2279 if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT) 2274 unsigned long arg)
2280 return media_changed(cdi, 1); 2275{
2276 struct cdrom_changer_info *info;
2277 int ret;
2281 2278
2282 if ((unsigned int)arg >= cdi->capacity) 2279 cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n");
2283 return -EINVAL;
2284 2280
2285 info = kmalloc(sizeof(*info), GFP_KERNEL); 2281 if (!CDROM_CAN(CDC_MEDIA_CHANGED))
2286 if (!info) 2282 return -ENOSYS;
2287 return -ENOMEM;
2288 2283
2289 if ((ret = cdrom_read_mech_status(cdi, info))) { 2284 /* cannot select disc or select current disc */
2290 kfree(info); 2285 if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT)
2291 return ret; 2286 return media_changed(cdi, 1);
2292 }
2293 2287
2294 changed = info->slots[arg].change; 2288 if ((unsigned int)arg >= cdi->capacity)
2295 kfree(info); 2289 return -EINVAL;
2296 return changed;
2297 }
2298 2290
2299 case CDROM_SET_OPTIONS: { 2291 info = kmalloc(sizeof(*info), GFP_KERNEL);
2300 cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n"); 2292 if (!info)
2301 /* options need to be in sync with capability. too late for 2293 return -ENOMEM;
2302 that, so we have to check each one separately... */
2303 switch (arg) {
2304 case CDO_USE_FFLAGS:
2305 case CDO_CHECK_TYPE:
2306 break;
2307 case CDO_LOCK:
2308 if (!CDROM_CAN(CDC_LOCK))
2309 return -ENOSYS;
2310 break;
2311 case 0:
2312 return cdi->options;
2313 /* default is basically CDO_[AUTO_CLOSE|AUTO_EJECT] */
2314 default:
2315 if (!CDROM_CAN(arg))
2316 return -ENOSYS;
2317 }
2318 cdi->options |= (int) arg;
2319 return cdi->options;
2320 }
2321 2294
2322 case CDROM_CLEAR_OPTIONS: { 2295 ret = cdrom_read_mech_status(cdi, info);
2323 cdinfo(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n"); 2296 if (!ret)
2324 cdi->options &= ~(int) arg; 2297 ret = info->slots[arg].change;
2325 return cdi->options; 2298 kfree(info);
2326 } 2299 return ret;
2300}
2327 2301
2328 case CDROM_SELECT_SPEED: { 2302static int cdrom_ioctl_set_options(struct cdrom_device_info *cdi,
2329 cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n"); 2303 unsigned long arg)
2330 if (!CDROM_CAN(CDC_SELECT_SPEED)) 2304{
2331 return -ENOSYS; 2305 cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n");
2332 return cdo->select_speed(cdi, arg);
2333 }
2334 2306
2335 case CDROM_SELECT_DISC: { 2307 /*
2336 cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n"); 2308 * Options need to be in sync with capability.
2337 if (!CDROM_CAN(CDC_SELECT_DISC)) 2309 * Too late for that, so we have to check each one separately.
2310 */
2311 switch (arg) {
2312 case CDO_USE_FFLAGS:
2313 case CDO_CHECK_TYPE:
2314 break;
2315 case CDO_LOCK:
2316 if (!CDROM_CAN(CDC_LOCK))
2317 return -ENOSYS;
2318 break;
2319 case 0:
2320 return cdi->options;
2321 /* default is basically CDO_[AUTO_CLOSE|AUTO_EJECT] */
2322 default:
2323 if (!CDROM_CAN(arg))
2338 return -ENOSYS; 2324 return -ENOSYS;
2325 }
2326 cdi->options |= (int) arg;
2327 return cdi->options;
2328}
2339 2329
2340 if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE)) 2330static int cdrom_ioctl_clear_options(struct cdrom_device_info *cdi,
2341 if ((int)arg >= cdi->capacity) 2331 unsigned long arg)
2342 return -EINVAL; 2332{
2343 2333 cdinfo(CD_DO_IOCTL, "entering CDROM_CLEAR_OPTIONS\n");
2344 /* cdo->select_disc is a hook to allow a driver-specific
2345 * way of seleting disc. However, since there is no
2346 * equiv hook for cdrom_slot_status this may not
2347 * actually be useful...
2348 */
2349 if (cdo->select_disc != NULL)
2350 return cdo->select_disc(cdi, arg);
2351
2352 /* no driver specific select_disc(), call our own */
2353 cdinfo(CD_CHANGER, "Using generic cdrom_select_disc()\n");
2354 return cdrom_select_disc(cdi, arg);
2355 }
2356 2334
2357 case CDROMRESET: { 2335 cdi->options &= ~(int) arg;
2358 if (!capable(CAP_SYS_ADMIN)) 2336 return cdi->options;
2359 return -EACCES; 2337}
2360 cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n");
2361 if (!CDROM_CAN(CDC_RESET))
2362 return -ENOSYS;
2363 invalidate_bdev(ip->i_bdev, 0);
2364 return cdo->reset(cdi);
2365 }
2366 2338
2367 case CDROM_LOCKDOOR: { 2339static int cdrom_ioctl_select_speed(struct cdrom_device_info *cdi,
2368 cdinfo(CD_DO_IOCTL, "%socking door.\n", arg ? "L" : "Unl"); 2340 unsigned long arg)
2369 if (!CDROM_CAN(CDC_LOCK)) 2341{
2370 return -EDRIVE_CANT_DO_THIS; 2342 cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_SPEED\n");
2371 keeplocked = arg ? 1 : 0;
2372 /* don't unlock the door on multiple opens,but allow root
2373 * to do so */
2374 if ((cdi->use_count != 1) && !arg && !capable(CAP_SYS_ADMIN))
2375 return -EBUSY;
2376 return cdo->lock_door(cdi, arg);
2377 }
2378 2343
2379 case CDROM_DEBUG: { 2344 if (!CDROM_CAN(CDC_SELECT_SPEED))
2380 if (!capable(CAP_SYS_ADMIN)) 2345 return -ENOSYS;
2381 return -EACCES; 2346 return cdi->ops->select_speed(cdi, arg);
2382 cdinfo(CD_DO_IOCTL, "%sabling debug.\n", arg ? "En" : "Dis"); 2347}
2383 debug = arg ? 1 : 0;
2384 return debug;
2385 }
2386 2348
2387 case CDROM_GET_CAPABILITY: { 2349static int cdrom_ioctl_select_disc(struct cdrom_device_info *cdi,
2388 cdinfo(CD_DO_IOCTL, "entering CDROM_GET_CAPABILITY\n"); 2350 unsigned long arg)
2389 return (cdo->capability & ~cdi->mask); 2351{
2390 } 2352 cdinfo(CD_DO_IOCTL, "entering CDROM_SELECT_DISC\n");
2353
2354 if (!CDROM_CAN(CDC_SELECT_DISC))
2355 return -ENOSYS;
2356
2357 if (arg != CDSL_CURRENT && arg != CDSL_NONE) {
2358 if ((int)arg >= cdi->capacity)
2359 return -EINVAL;
2360 }
2361
2362 /*
2363 * ->select_disc is a hook to allow a driver-specific way of
2364 * seleting disc. However, since there is no equivalent hook for
2365 * cdrom_slot_status this may not actually be useful...
2366 */
2367 if (cdi->ops->select_disc)
2368 return cdi->ops->select_disc(cdi, arg);
2369
2370 cdinfo(CD_CHANGER, "Using generic cdrom_select_disc()\n");
2371 return cdrom_select_disc(cdi, arg);
2372}
2373
2374static int cdrom_ioctl_reset(struct cdrom_device_info *cdi,
2375 struct block_device *bdev)
2376{
2377 cdinfo(CD_DO_IOCTL, "entering CDROM_RESET\n");
2378
2379 if (!capable(CAP_SYS_ADMIN))
2380 return -EACCES;
2381 if (!CDROM_CAN(CDC_RESET))
2382 return -ENOSYS;
2383 invalidate_bdev(bdev, 0);
2384 return cdi->ops->reset(cdi);
2385}
2386
2387static int cdrom_ioctl_lock_door(struct cdrom_device_info *cdi,
2388 unsigned long arg)
2389{
2390 cdinfo(CD_DO_IOCTL, "%socking door.\n", arg ? "L" : "Unl");
2391
2392 if (!CDROM_CAN(CDC_LOCK))
2393 return -EDRIVE_CANT_DO_THIS;
2394
2395 keeplocked = arg ? 1 : 0;
2396
2397 /*
2398 * Don't unlock the door on multiple opens by default, but allow
2399 * root to do so.
2400 */
2401 if (cdi->use_count != 1 && !arg && !capable(CAP_SYS_ADMIN))
2402 return -EBUSY;
2403 return cdi->ops->lock_door(cdi, arg);
2404}
2405
2406static int cdrom_ioctl_debug(struct cdrom_device_info *cdi,
2407 unsigned long arg)
2408{
2409 cdinfo(CD_DO_IOCTL, "%sabling debug.\n", arg ? "En" : "Dis");
2410
2411 if (!capable(CAP_SYS_ADMIN))
2412 return -EACCES;
2413 debug = arg ? 1 : 0;
2414 return debug;
2415}
2391 2416
2392/* The following function is implemented, although very few audio 2417static int cdrom_ioctl_get_capability(struct cdrom_device_info *cdi)
2418{
2419 cdinfo(CD_DO_IOCTL, "entering CDROM_GET_CAPABILITY\n");
2420 return (cdi->ops->capability & ~cdi->mask);
2421}
2422
2423/*
2424 * The following function is implemented, although very few audio
2393 * discs give Universal Product Code information, which should just be 2425 * discs give Universal Product Code information, which should just be
2394 * the Medium Catalog Number on the box. Note, that the way the code 2426 * the Medium Catalog Number on the box. Note, that the way the code
2395 * is written on the CD is /not/ uniform across all discs! 2427 * is written on the CD is /not/ uniform across all discs!
2396 */ 2428 */
2397 case CDROM_GET_MCN: { 2429static int cdrom_ioctl_get_mcn(struct cdrom_device_info *cdi,
2398 struct cdrom_mcn mcn; 2430 void __user *argp)
2399 cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCN\n"); 2431{
2400 if (!(cdo->capability & CDC_MCN)) 2432 struct cdrom_mcn mcn;
2401 return -ENOSYS; 2433 int ret;
2402 if ((ret=cdo->get_mcn(cdi, &mcn)))
2403 return ret;
2404 IOCTL_OUT(arg, struct cdrom_mcn, mcn);
2405 cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n");
2406 return 0;
2407 }
2408 2434
2409 case CDROM_DRIVE_STATUS: { 2435 cdinfo(CD_DO_IOCTL, "entering CDROM_GET_MCN\n");
2410 cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n");
2411 if (!(cdo->capability & CDC_DRIVE_STATUS))
2412 return -ENOSYS;
2413 if (!CDROM_CAN(CDC_SELECT_DISC))
2414 return cdo->drive_status(cdi, CDSL_CURRENT);
2415 if ((arg == CDSL_CURRENT) || (arg == CDSL_NONE))
2416 return cdo->drive_status(cdi, CDSL_CURRENT);
2417 if (((int)arg >= cdi->capacity))
2418 return -EINVAL;
2419 return cdrom_slot_status(cdi, arg);
2420 }
2421 2436
2422 /* Ok, this is where problems start. The current interface for the 2437 if (!(cdi->ops->capability & CDC_MCN))
2423 CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption 2438 return -ENOSYS;
2424 that CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunatly, 2439 ret = cdi->ops->get_mcn(cdi, &mcn);
2425 while this is often the case, it is also very common for CDs to 2440 if (ret)
2426 have some tracks with data, and some tracks with audio. Just 2441 return ret;
2427 because I feel like it, I declare the following to be the best
2428 way to cope. If the CD has ANY data tracks on it, it will be
2429 returned as a data CD. If it has any XA tracks, I will return
2430 it as that. Now I could simplify this interface by combining these
2431 returns with the above, but this more clearly demonstrates
2432 the problem with the current interface. Too bad this wasn't
2433 designed to use bitmasks... -Erik
2434
2435 Well, now we have the option CDS_MIXED: a mixed-type CD.
2436 User level programmers might feel the ioctl is not very useful.
2437 ---david
2438 */
2439 case CDROM_DISC_STATUS: {
2440 tracktype tracks;
2441 cdinfo(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n");
2442 cdrom_count_tracks(cdi, &tracks);
2443 if (tracks.error)
2444 return(tracks.error);
2445
2446 /* Policy mode on */
2447 if (tracks.audio > 0) {
2448 if (tracks.data==0 && tracks.cdi==0 && tracks.xa==0)
2449 return CDS_AUDIO;
2450 else
2451 return CDS_MIXED;
2452 }
2453 if (tracks.cdi > 0) return CDS_XA_2_2;
2454 if (tracks.xa > 0) return CDS_XA_2_1;
2455 if (tracks.data > 0) return CDS_DATA_1;
2456 /* Policy mode off */
2457 2442
2458 cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognize!\n"); 2443 if (copy_to_user(argp, &mcn, sizeof(mcn)))
2459 return CDS_NO_INFO; 2444 return -EFAULT;
2460 } 2445 cdinfo(CD_DO_IOCTL, "CDROM_GET_MCN successful\n");
2446 return 0;
2447}
2461 2448
2462 case CDROM_CHANGER_NSLOTS: { 2449static int cdrom_ioctl_drive_status(struct cdrom_device_info *cdi,
2463 cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n"); 2450 unsigned long arg)
2464 return cdi->capacity; 2451{
2465 } 2452 cdinfo(CD_DO_IOCTL, "entering CDROM_DRIVE_STATUS\n");
2453
2454 if (!(cdi->ops->capability & CDC_DRIVE_STATUS))
2455 return -ENOSYS;
2456 if (!CDROM_CAN(CDC_SELECT_DISC) ||
2457 (arg == CDSL_CURRENT || arg == CDSL_NONE))
2458 return cdi->ops->drive_status(cdi, CDSL_CURRENT);
2459 if (((int)arg >= cdi->capacity))
2460 return -EINVAL;
2461 return cdrom_slot_status(cdi, arg);
2462}
2463
2464/*
2465 * Ok, this is where problems start. The current interface for the
2466 * CDROM_DISC_STATUS ioctl is flawed. It makes the false assumption that
2467 * CDs are all CDS_DATA_1 or all CDS_AUDIO, etc. Unfortunatly, while this
2468 * is often the case, it is also very common for CDs to have some tracks
2469 * with data, and some tracks with audio. Just because I feel like it,
2470 * I declare the following to be the best way to cope. If the CD has ANY
2471 * data tracks on it, it will be returned as a data CD. If it has any XA
2472 * tracks, I will return it as that. Now I could simplify this interface
2473 * by combining these returns with the above, but this more clearly
2474 * demonstrates the problem with the current interface. Too bad this
2475 * wasn't designed to use bitmasks... -Erik
2476 *
2477 * Well, now we have the option CDS_MIXED: a mixed-type CD.
2478 * User level programmers might feel the ioctl is not very useful.
2479 * ---david
2480 */
2481static int cdrom_ioctl_disc_status(struct cdrom_device_info *cdi)
2482{
2483 tracktype tracks;
2484
2485 cdinfo(CD_DO_IOCTL, "entering CDROM_DISC_STATUS\n");
2486
2487 cdrom_count_tracks(cdi, &tracks);
2488 if (tracks.error)
2489 return tracks.error;
2490
2491 /* Policy mode on */
2492 if (tracks.audio > 0) {
2493 if (!tracks.data && !tracks.cdi && !tracks.xa)
2494 return CDS_AUDIO;
2495 else
2496 return CDS_MIXED;
2466 } 2497 }
2467 2498
2468 /* use the ioctls that are implemented through the generic_packet() 2499 if (tracks.cdi > 0)
2469 interface. this may look at bit funny, but if -ENOTTY is 2500 return CDS_XA_2_2;
2470 returned that particular ioctl is not implemented and we 2501 if (tracks.xa > 0)
2471 let it go through the device specific ones. */ 2502 return CDS_XA_2_1;
2503 if (tracks.data > 0)
2504 return CDS_DATA_1;
2505 /* Policy mode off */
2506
2507 cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognize!\n");
2508 return CDS_NO_INFO;
2509}
2510
2511static int cdrom_ioctl_changer_nslots(struct cdrom_device_info *cdi)
2512{
2513 cdinfo(CD_DO_IOCTL, "entering CDROM_CHANGER_NSLOTS\n");
2514 return cdi->capacity;
2515}
2516
2517static int cdrom_ioctl_get_subchnl(struct cdrom_device_info *cdi,
2518 void __user *argp)
2519{
2520 struct cdrom_subchnl q;
2521 u8 requested, back;
2522 int ret;
2523
2524 /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/
2525
2526 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2527 return -ENOSYS;
2528 if (copy_from_user(&q, argp, sizeof(q)))
2529 return -EFAULT;
2530
2531 requested = q.cdsc_format;
2532 if (requested != CDROM_MSF && requested != CDROM_LBA)
2533 return -EINVAL;
2534 q.cdsc_format = CDROM_MSF;
2535
2536 ret = cdi->ops->audio_ioctl(cdi, CDROMSUBCHNL, &q);
2537 if (ret)
2538 return ret;
2539
2540 back = q.cdsc_format; /* local copy */
2541 sanitize_format(&q.cdsc_absaddr, &back, requested);
2542 sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
2543
2544 if (copy_to_user(argp, &q, sizeof(q)))
2545 return -EFAULT;
2546 /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
2547 return 0;
2548}
2549
2550static int cdrom_ioctl_read_tochdr(struct cdrom_device_info *cdi,
2551 void __user *argp)
2552{
2553 struct cdrom_tochdr header;
2554 int ret;
2555
2556 /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */
2557
2558 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2559 return -ENOSYS;
2560 if (copy_from_user(&header, argp, sizeof(header)))
2561 return -EFAULT;
2562
2563 ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header);
2564 if (ret)
2565 return ret;
2566
2567 if (copy_to_user(argp, &header, sizeof(header)))
2568 return -EFAULT;
2569 /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */
2570 return 0;
2571}
2572
2573static int cdrom_ioctl_read_tocentry(struct cdrom_device_info *cdi,
2574 void __user *argp)
2575{
2576 struct cdrom_tocentry entry;
2577 u8 requested_format;
2578 int ret;
2579
2580 /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */
2581
2582 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2583 return -ENOSYS;
2584 if (copy_from_user(&entry, argp, sizeof(entry)))
2585 return -EFAULT;
2586
2587 requested_format = entry.cdte_format;
2588 if (requested_format != CDROM_MSF && requested_format != CDROM_LBA)
2589 return -EINVAL;
2590 /* make interface to low-level uniform */
2591 entry.cdte_format = CDROM_MSF;
2592 ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry);
2593 if (ret)
2594 return ret;
2595 sanitize_format(&entry.cdte_addr, &entry.cdte_format, requested_format);
2596
2597 if (copy_to_user(argp, &entry, sizeof(entry)))
2598 return -EFAULT;
2599 /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */
2600 return 0;
2601}
2602
2603static int cdrom_ioctl_play_msf(struct cdrom_device_info *cdi,
2604 void __user *argp)
2605{
2606 struct cdrom_msf msf;
2607
2608 cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
2609
2610 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2611 return -ENOSYS;
2612 if (copy_from_user(&msf, argp, sizeof(msf)))
2613 return -EFAULT;
2614 return cdi->ops->audio_ioctl(cdi, CDROMPLAYMSF, &msf);
2615}
2616
2617static int cdrom_ioctl_play_trkind(struct cdrom_device_info *cdi,
2618 void __user *argp)
2619{
2620 struct cdrom_ti ti;
2621 int ret;
2622
2623 cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
2624
2625 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2626 return -ENOSYS;
2627 if (copy_from_user(&ti, argp, sizeof(ti)))
2628 return -EFAULT;
2629
2630 ret = check_for_audio_disc(cdi, cdi->ops);
2631 if (ret)
2632 return ret;
2633 return cdi->ops->audio_ioctl(cdi, CDROMPLAYTRKIND, &ti);
2634}
2635static int cdrom_ioctl_volctrl(struct cdrom_device_info *cdi,
2636 void __user *argp)
2637{
2638 struct cdrom_volctrl volume;
2639
2640 cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n");
2641
2642 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2643 return -ENOSYS;
2644 if (copy_from_user(&volume, argp, sizeof(volume)))
2645 return -EFAULT;
2646 return cdi->ops->audio_ioctl(cdi, CDROMVOLCTRL, &volume);
2647}
2648
2649static int cdrom_ioctl_volread(struct cdrom_device_info *cdi,
2650 void __user *argp)
2651{
2652 struct cdrom_volctrl volume;
2653 int ret;
2654
2655 cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n");
2656
2657 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2658 return -ENOSYS;
2659
2660 ret = cdi->ops->audio_ioctl(cdi, CDROMVOLREAD, &volume);
2661 if (ret)
2662 return ret;
2663
2664 if (copy_to_user(argp, &volume, sizeof(volume)))
2665 return -EFAULT;
2666 return 0;
2667}
2668
2669static int cdrom_ioctl_audioctl(struct cdrom_device_info *cdi,
2670 unsigned int cmd)
2671{
2672 int ret;
2673
2674 cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n");
2675
2676 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2677 return -ENOSYS;
2678 ret = check_for_audio_disc(cdi, cdi->ops);
2679 if (ret)
2680 return ret;
2681 return cdi->ops->audio_ioctl(cdi, cmd, NULL);
2682}
2683
2684/*
2685 * Just about every imaginable ioctl is supported in the Uniform layer
2686 * these days.
2687 * ATAPI / SCSI specific code now mainly resides in mmc_ioctl().
2688 */
2689int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
2690 struct inode *ip, unsigned int cmd, unsigned long arg)
2691{
2692 void __user *argp = (void __user *)arg;
2693 int ret;
2694
2695 /*
2696 * Try the generic SCSI command ioctl's first.
2697 */
2698 ret = scsi_cmd_ioctl(file, ip->i_bdev->bd_disk, cmd, argp);
2699 if (ret != -ENOTTY)
2700 return ret;
2701
2702 switch (cmd) {
2703 case CDROMMULTISESSION:
2704 return cdrom_ioctl_multisession(cdi, argp);
2705 case CDROMEJECT:
2706 return cdrom_ioctl_eject(cdi);
2707 case CDROMCLOSETRAY:
2708 return cdrom_ioctl_closetray(cdi);
2709 case CDROMEJECT_SW:
2710 return cdrom_ioctl_eject_sw(cdi, arg);
2711 case CDROM_MEDIA_CHANGED:
2712 return cdrom_ioctl_media_changed(cdi, arg);
2713 case CDROM_SET_OPTIONS:
2714 return cdrom_ioctl_set_options(cdi, arg);
2715 case CDROM_CLEAR_OPTIONS:
2716 return cdrom_ioctl_clear_options(cdi, arg);
2717 case CDROM_SELECT_SPEED:
2718 return cdrom_ioctl_select_speed(cdi, arg);
2719 case CDROM_SELECT_DISC:
2720 return cdrom_ioctl_select_disc(cdi, arg);
2721 case CDROMRESET:
2722 return cdrom_ioctl_reset(cdi, ip->i_bdev);
2723 case CDROM_LOCKDOOR:
2724 return cdrom_ioctl_lock_door(cdi, arg);
2725 case CDROM_DEBUG:
2726 return cdrom_ioctl_debug(cdi, arg);
2727 case CDROM_GET_CAPABILITY:
2728 return cdrom_ioctl_get_capability(cdi);
2729 case CDROM_GET_MCN:
2730 return cdrom_ioctl_get_mcn(cdi, argp);
2731 case CDROM_DRIVE_STATUS:
2732 return cdrom_ioctl_drive_status(cdi, arg);
2733 case CDROM_DISC_STATUS:
2734 return cdrom_ioctl_disc_status(cdi);
2735 case CDROM_CHANGER_NSLOTS:
2736 return cdrom_ioctl_changer_nslots(cdi);
2737 }
2738
2739 /*
2740 * Use the ioctls that are implemented through the generic_packet()
2741 * interface. this may look at bit funny, but if -ENOTTY is
2742 * returned that particular ioctl is not implemented and we
2743 * let it go through the device specific ones.
2744 */
2472 if (CDROM_CAN(CDC_GENERIC_PACKET)) { 2745 if (CDROM_CAN(CDC_GENERIC_PACKET)) {
2473 ret = mmc_ioctl(cdi, cmd, arg); 2746 ret = mmc_ioctl(cdi, cmd, arg);
2474 if (ret != -ENOTTY) { 2747 if (ret != -ENOTTY)
2475 return ret; 2748 return ret;
2476 }
2477 } 2749 }
2478 2750
2479 /* note: most of the cdinfo() calls are commented out here, 2751 /*
2480 because they fill up the sys log when CD players poll 2752 * Note: most of the cdinfo() calls are commented out here,
2481 the drive. */ 2753 * because they fill up the sys log when CD players poll
2754 * the drive.
2755 */
2482 switch (cmd) { 2756 switch (cmd) {
2483 case CDROMSUBCHNL: { 2757 case CDROMSUBCHNL:
2484 struct cdrom_subchnl q; 2758 return cdrom_ioctl_get_subchnl(cdi, argp);
2485 u_char requested, back; 2759 case CDROMREADTOCHDR:
2486 if (!CDROM_CAN(CDC_PLAY_AUDIO)) 2760 return cdrom_ioctl_read_tochdr(cdi, argp);
2487 return -ENOSYS; 2761 case CDROMREADTOCENTRY:
2488 /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/ 2762 return cdrom_ioctl_read_tocentry(cdi, argp);
2489 IOCTL_IN(arg, struct cdrom_subchnl, q); 2763 case CDROMPLAYMSF:
2490 requested = q.cdsc_format; 2764 return cdrom_ioctl_play_msf(cdi, argp);
2491 if (!((requested == CDROM_MSF) || 2765 case CDROMPLAYTRKIND:
2492 (requested == CDROM_LBA))) 2766 return cdrom_ioctl_play_trkind(cdi, argp);
2493 return -EINVAL; 2767 case CDROMVOLCTRL:
2494 q.cdsc_format = CDROM_MSF; 2768 return cdrom_ioctl_volctrl(cdi, argp);
2495 if ((ret=cdo->audio_ioctl(cdi, cmd, &q))) 2769 case CDROMVOLREAD:
2496 return ret; 2770 return cdrom_ioctl_volread(cdi, argp);
2497 back = q.cdsc_format; /* local copy */
2498 sanitize_format(&q.cdsc_absaddr, &back, requested);
2499 sanitize_format(&q.cdsc_reladdr, &q.cdsc_format, requested);
2500 IOCTL_OUT(arg, struct cdrom_subchnl, q);
2501 /* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
2502 return 0;
2503 }
2504 case CDROMREADTOCHDR: {
2505 struct cdrom_tochdr header;
2506 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2507 return -ENOSYS;
2508 /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */
2509 IOCTL_IN(arg, struct cdrom_tochdr, header);
2510 if ((ret=cdo->audio_ioctl(cdi, cmd, &header)))
2511 return ret;
2512 IOCTL_OUT(arg, struct cdrom_tochdr, header);
2513 /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCHDR successful\n"); */
2514 return 0;
2515 }
2516 case CDROMREADTOCENTRY: {
2517 struct cdrom_tocentry entry;
2518 u_char requested_format;
2519 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2520 return -ENOSYS;
2521 /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */
2522 IOCTL_IN(arg, struct cdrom_tocentry, entry);
2523 requested_format = entry.cdte_format;
2524 if (!((requested_format == CDROM_MSF) ||
2525 (requested_format == CDROM_LBA)))
2526 return -EINVAL;
2527 /* make interface to low-level uniform */
2528 entry.cdte_format = CDROM_MSF;
2529 if ((ret=cdo->audio_ioctl(cdi, cmd, &entry)))
2530 return ret;
2531 sanitize_format(&entry.cdte_addr,
2532 &entry.cdte_format, requested_format);
2533 IOCTL_OUT(arg, struct cdrom_tocentry, entry);
2534 /* cdinfo(CD_DO_IOCTL, "CDROMREADTOCENTRY successful\n"); */
2535 return 0;
2536 }
2537 case CDROMPLAYMSF: {
2538 struct cdrom_msf msf;
2539 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2540 return -ENOSYS;
2541 cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
2542 IOCTL_IN(arg, struct cdrom_msf, msf);
2543 return cdo->audio_ioctl(cdi, cmd, &msf);
2544 }
2545 case CDROMPLAYTRKIND: {
2546 struct cdrom_ti ti;
2547 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2548 return -ENOSYS;
2549 cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
2550 IOCTL_IN(arg, struct cdrom_ti, ti);
2551 CHECKAUDIO;
2552 return cdo->audio_ioctl(cdi, cmd, &ti);
2553 }
2554 case CDROMVOLCTRL: {
2555 struct cdrom_volctrl volume;
2556 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2557 return -ENOSYS;
2558 cdinfo(CD_DO_IOCTL, "entering CDROMVOLCTRL\n");
2559 IOCTL_IN(arg, struct cdrom_volctrl, volume);
2560 return cdo->audio_ioctl(cdi, cmd, &volume);
2561 }
2562 case CDROMVOLREAD: {
2563 struct cdrom_volctrl volume;
2564 if (!CDROM_CAN(CDC_PLAY_AUDIO))
2565 return -ENOSYS;
2566 cdinfo(CD_DO_IOCTL, "entering CDROMVOLREAD\n");
2567 if ((ret=cdo->audio_ioctl(cdi, cmd, &volume)))
2568 return ret;
2569 IOCTL_OUT(arg, struct cdrom_volctrl, volume);
2570 return 0;
2571 }
2572 case CDROMSTART: 2771 case CDROMSTART:
2573 case CDROMSTOP: 2772 case CDROMSTOP:
2574 case CDROMPAUSE: 2773 case CDROMPAUSE:
2575 case CDROMRESUME: { 2774 case CDROMRESUME:
2576 if (!CDROM_CAN(CDC_PLAY_AUDIO)) 2775 return cdrom_ioctl_audioctl(cdi, cmd);
2577 return -ENOSYS; 2776 }
2578 cdinfo(CD_DO_IOCTL, "doing audio ioctl (start/stop/pause/resume)\n");
2579 CHECKAUDIO;
2580 return cdo->audio_ioctl(cdi, cmd, NULL);
2581 }
2582 } /* switch */
2583 2777
2584 /* do the device specific ioctls */
2585 if (CDROM_CAN(CDC_IOCTLS))
2586 return cdo->dev_ioctl(cdi, cmd, arg);
2587
2588 return -ENOSYS; 2778 return -ENOSYS;
2589} 2779}
2590 2780