diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2006-04-02 00:08:05 -0500 |
---|---|---|
committer | Dmitry Torokhov <dtor_core@ameritech.net> | 2006-04-02 00:08:05 -0500 |
commit | 95d465fd750897ab32462a6702fbfe1b122cbbc0 (patch) | |
tree | 65c38b2f11c51bb6932e44dd6c92f15b0091abfe /drivers/cdrom | |
parent | 642fde17dceceb56c7ba2762733ac688666ae657 (diff) | |
parent | 683aa4012f53b2ada0f430487e05d37b0d94e90a (diff) |
Manual merge with Linus.
Conflicts:
arch/powerpc/kernel/setup-common.c
drivers/input/keyboard/hil_kbd.c
drivers/input/mouse/hil_ptr.c
Diffstat (limited to 'drivers/cdrom')
-rw-r--r-- | drivers/cdrom/cdrom.c | 874 | ||||
-rw-r--r-- | drivers/cdrom/cdu31a.c | 8 | ||||
-rw-r--r-- | drivers/cdrom/cm206.c | 52 | ||||
-rw-r--r-- | drivers/cdrom/sbpcd.c | 720 | ||||
-rw-r--r-- | drivers/cdrom/viocd.c | 2 |
5 files changed, 917 insertions, 739 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 | 2198 | static 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 | */ | ||
2203 | int 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); | 2231 | static 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); | 2248 | static 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: { | 2257 | static 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 */ | 2273 | static 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: { | 2302 | static 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)) | 2330 | static 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: { | 2339 | static 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: { | 2349 | static 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 | |||
2374 | static 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 | |||
2387 | static 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 | |||
2406 | static 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 | 2417 | static 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: { | 2429 | static 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: { | 2449 | static 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 | */ | ||
2481 | static 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 | |||
2511 | static 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 | |||
2517 | static 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 | |||
2550 | static 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 | |||
2573 | static 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 | |||
2603 | static 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 | |||
2617 | static 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 | } | ||
2635 | static 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 | |||
2649 | static 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 | |||
2669 | static 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 | */ | ||
2689 | int 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 | ||
diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index 378e88d20757..72ffd64e8b1e 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c | |||
@@ -2668,7 +2668,7 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi, | |||
2668 | return retval; | 2668 | return retval; |
2669 | } | 2669 | } |
2670 | 2670 | ||
2671 | static int scd_dev_ioctl(struct cdrom_device_info *cdi, | 2671 | static int scd_read_audio(struct cdrom_device_info *cdi, |
2672 | unsigned int cmd, unsigned long arg) | 2672 | unsigned int cmd, unsigned long arg) |
2673 | { | 2673 | { |
2674 | void __user *argp = (void __user *)arg; | 2674 | void __user *argp = (void __user *)arg; |
@@ -2894,11 +2894,10 @@ static struct cdrom_device_ops scd_dops = { | |||
2894 | .get_mcn = scd_get_mcn, | 2894 | .get_mcn = scd_get_mcn, |
2895 | .reset = scd_reset, | 2895 | .reset = scd_reset, |
2896 | .audio_ioctl = scd_audio_ioctl, | 2896 | .audio_ioctl = scd_audio_ioctl, |
2897 | .dev_ioctl = scd_dev_ioctl, | ||
2898 | .capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | | 2897 | .capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | |
2899 | CDC_SELECT_SPEED | CDC_MULTI_SESSION | | 2898 | CDC_SELECT_SPEED | CDC_MULTI_SESSION | |
2900 | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | | 2899 | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | |
2901 | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, | 2900 | CDC_RESET | CDC_DRIVE_STATUS, |
2902 | .n_minors = 1, | 2901 | .n_minors = 1, |
2903 | }; | 2902 | }; |
2904 | 2903 | ||
@@ -2936,6 +2935,9 @@ static int scd_block_ioctl(struct inode *inode, struct file *file, | |||
2936 | case CDROMCLOSETRAY: | 2935 | case CDROMCLOSETRAY: |
2937 | retval = scd_tray_move(&scd_info, 0); | 2936 | retval = scd_tray_move(&scd_info, 0); |
2938 | break; | 2937 | break; |
2938 | case CDROMREADAUDIO: | ||
2939 | retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg); | ||
2940 | break; | ||
2939 | default: | 2941 | default: |
2940 | retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg); | 2942 | retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg); |
2941 | } | 2943 | } |
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c index ce127f7ec0f6..f43a988dd413 100644 --- a/drivers/cdrom/cm206.c +++ b/drivers/cdrom/cm206.c | |||
@@ -218,12 +218,12 @@ static int cm206_base = CM206_BASE; | |||
218 | static int cm206_irq = CM206_IRQ; | 218 | static int cm206_irq = CM206_IRQ; |
219 | #ifdef MODULE | 219 | #ifdef MODULE |
220 | static int cm206[2] = { 0, 0 }; /* for compatible `insmod' parameter passing */ | 220 | static int cm206[2] = { 0, 0 }; /* for compatible `insmod' parameter passing */ |
221 | module_param_array(cm206, int, NULL, 0); /* base,irq or irq,base */ | ||
221 | #endif | 222 | #endif |
222 | 223 | ||
223 | MODULE_PARM(cm206_base, "i"); /* base */ | 224 | module_param(cm206_base, int, 0); /* base */ |
224 | MODULE_PARM(cm206_irq, "i"); /* irq */ | 225 | module_param(cm206_irq, int, 0); /* irq */ |
225 | MODULE_PARM(cm206, "1-2i"); /* base,irq or irq,base */ | 226 | module_param(auto_probe, bool, 0); /* auto probe base and irq */ |
226 | MODULE_PARM(auto_probe, "i"); /* auto probe base and irq */ | ||
227 | MODULE_LICENSE("GPL"); | 227 | MODULE_LICENSE("GPL"); |
228 | 228 | ||
229 | #define POLLOOP 100 /* milliseconds */ | 229 | #define POLLOOP 100 /* milliseconds */ |
@@ -1157,32 +1157,6 @@ static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, | |||
1157 | } | 1157 | } |
1158 | } | 1158 | } |
1159 | 1159 | ||
1160 | /* Ioctl. These ioctls are specific to the cm206 driver. I have made | ||
1161 | some driver statistics accessible through ioctl calls. | ||
1162 | */ | ||
1163 | |||
1164 | static int cm206_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, | ||
1165 | unsigned long arg) | ||
1166 | { | ||
1167 | switch (cmd) { | ||
1168 | #ifdef STATISTICS | ||
1169 | case CM206CTL_GET_STAT: | ||
1170 | if (arg >= NR_STATS) | ||
1171 | return -EINVAL; | ||
1172 | else | ||
1173 | return cd->stats[arg]; | ||
1174 | case CM206CTL_GET_LAST_STAT: | ||
1175 | if (arg >= NR_STATS) | ||
1176 | return -EINVAL; | ||
1177 | else | ||
1178 | return cd->last_stat[arg]; | ||
1179 | #endif | ||
1180 | default: | ||
1181 | debug(("Unknown ioctl call 0x%x\n", cmd)); | ||
1182 | return -EINVAL; | ||
1183 | } | ||
1184 | } | ||
1185 | |||
1186 | static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr) | 1160 | static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr) |
1187 | { | 1161 | { |
1188 | if (cd != NULL) { | 1162 | if (cd != NULL) { |
@@ -1321,11 +1295,10 @@ static struct cdrom_device_ops cm206_dops = { | |||
1321 | .get_mcn = cm206_get_upc, | 1295 | .get_mcn = cm206_get_upc, |
1322 | .reset = cm206_reset, | 1296 | .reset = cm206_reset, |
1323 | .audio_ioctl = cm206_audio_ioctl, | 1297 | .audio_ioctl = cm206_audio_ioctl, |
1324 | .dev_ioctl = cm206_ioctl, | ||
1325 | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | | 1298 | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | |
1326 | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | | 1299 | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | |
1327 | CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED | | 1300 | CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED | |
1328 | CDC_IOCTLS | CDC_DRIVE_STATUS, | 1301 | CDC_DRIVE_STATUS, |
1329 | .n_minors = 1, | 1302 | .n_minors = 1, |
1330 | }; | 1303 | }; |
1331 | 1304 | ||
@@ -1350,6 +1323,21 @@ static int cm206_block_release(struct inode *inode, struct file *file) | |||
1350 | static int cm206_block_ioctl(struct inode *inode, struct file *file, | 1323 | static int cm206_block_ioctl(struct inode *inode, struct file *file, |
1351 | unsigned cmd, unsigned long arg) | 1324 | unsigned cmd, unsigned long arg) |
1352 | { | 1325 | { |
1326 | switch (cmd) { | ||
1327 | #ifdef STATISTICS | ||
1328 | case CM206CTL_GET_STAT: | ||
1329 | if (arg >= NR_STATS) | ||
1330 | return -EINVAL; | ||
1331 | return cd->stats[arg]; | ||
1332 | case CM206CTL_GET_LAST_STAT: | ||
1333 | if (arg >= NR_STATS) | ||
1334 | return -EINVAL; | ||
1335 | return cd->last_stat[arg]; | ||
1336 | #endif | ||
1337 | default: | ||
1338 | break; | ||
1339 | } | ||
1340 | |||
1353 | return cdrom_ioctl(file, &cm206_info, inode, cmd, arg); | 1341 | return cdrom_ioctl(file, &cm206_info, inode, cmd, arg); |
1354 | } | 1342 | } |
1355 | 1343 | ||
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 466e9c2974bd..05c9e865ecaf 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c | |||
@@ -464,8 +464,13 @@ static int sbpcd[] = | |||
464 | static __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock); | 464 | static __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock); |
465 | static struct request_queue *sbpcd_queue; | 465 | static struct request_queue *sbpcd_queue; |
466 | 466 | ||
467 | MODULE_PARM(sbpcd, "2i"); | 467 | /* You can only set the first pair, from old MODULE_PARM code. */ |
468 | MODULE_PARM(max_drives, "i"); | 468 | static int sbpcd_set(const char *val, struct kernel_param *kp) |
469 | { | ||
470 | get_options((char *)val, 2, (int *)sbpcd); | ||
471 | return 0; | ||
472 | } | ||
473 | module_param_call(sbpcd, sbpcd_set, NULL, NULL, 0); | ||
469 | 474 | ||
470 | #define NUM_PROBE (sizeof(sbpcd) / sizeof(int)) | 475 | #define NUM_PROBE (sizeof(sbpcd) / sizeof(int)) |
471 | 476 | ||
@@ -553,6 +558,7 @@ static unsigned char msgnum; | |||
553 | static char msgbuf[80]; | 558 | static char msgbuf[80]; |
554 | 559 | ||
555 | static int max_drives = MAX_DRIVES; | 560 | static int max_drives = MAX_DRIVES; |
561 | module_param(max_drives, int, 0); | ||
556 | #ifndef MODULE | 562 | #ifndef MODULE |
557 | static unsigned char setup_done; | 563 | static unsigned char setup_done; |
558 | static const char *str_sb_l = "soundblaster"; | 564 | static const char *str_sb_l = "soundblaster"; |
@@ -4160,332 +4166,6 @@ static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_mu | |||
4160 | return 0; | 4166 | return 0; |
4161 | } | 4167 | } |
4162 | 4168 | ||
4163 | /*==========================================================================*/ | ||
4164 | /*==========================================================================*/ | ||
4165 | /* | ||
4166 | * ioctl support | ||
4167 | */ | ||
4168 | static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, | ||
4169 | u_long arg) | ||
4170 | { | ||
4171 | struct sbpcd_drive *p = cdi->handle; | ||
4172 | int i; | ||
4173 | |||
4174 | msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg); | ||
4175 | if (p->drv_id==-1) { | ||
4176 | msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); | ||
4177 | return (-ENXIO); /* no such drive */ | ||
4178 | } | ||
4179 | down(&ioctl_read_sem); | ||
4180 | if (p != current_drive) | ||
4181 | switch_drive(p); | ||
4182 | |||
4183 | msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); | ||
4184 | switch (cmd) /* Sun-compatible */ | ||
4185 | { | ||
4186 | case DDIOCSDBG: /* DDI Debug */ | ||
4187 | if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM); | ||
4188 | i=sbpcd_dbg_ioctl(arg,1); | ||
4189 | RETURN_UP(i); | ||
4190 | case CDROMRESET: /* hard reset the drive */ | ||
4191 | msg(DBG_IOC,"ioctl: CDROMRESET entered.\n"); | ||
4192 | i=DriveReset(); | ||
4193 | current_drive->audio_state=0; | ||
4194 | RETURN_UP(i); | ||
4195 | |||
4196 | case CDROMREADMODE1: | ||
4197 | msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); | ||
4198 | #ifdef SAFE_MIXED | ||
4199 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4200 | #endif /* SAFE_MIXED */ | ||
4201 | cc_ModeSelect(CD_FRAMESIZE); | ||
4202 | cc_ModeSense(); | ||
4203 | current_drive->mode=READ_M1; | ||
4204 | RETURN_UP(0); | ||
4205 | |||
4206 | case CDROMREADMODE2: /* not usable at the moment */ | ||
4207 | msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); | ||
4208 | #ifdef SAFE_MIXED | ||
4209 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4210 | #endif /* SAFE_MIXED */ | ||
4211 | cc_ModeSelect(CD_FRAMESIZE_RAW1); | ||
4212 | cc_ModeSense(); | ||
4213 | current_drive->mode=READ_M2; | ||
4214 | RETURN_UP(0); | ||
4215 | |||
4216 | case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */ | ||
4217 | msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n"); | ||
4218 | if (current_drive->sbp_audsiz>0) | ||
4219 | vfree(current_drive->aud_buf); | ||
4220 | current_drive->aud_buf=NULL; | ||
4221 | current_drive->sbp_audsiz=arg; | ||
4222 | |||
4223 | if (current_drive->sbp_audsiz>16) | ||
4224 | { | ||
4225 | current_drive->sbp_audsiz = 0; | ||
4226 | RETURN_UP(current_drive->sbp_audsiz); | ||
4227 | } | ||
4228 | |||
4229 | if (current_drive->sbp_audsiz>0) | ||
4230 | { | ||
4231 | current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW); | ||
4232 | if (current_drive->aud_buf==NULL) | ||
4233 | { | ||
4234 | msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz); | ||
4235 | current_drive->sbp_audsiz=0; | ||
4236 | } | ||
4237 | else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz); | ||
4238 | } | ||
4239 | RETURN_UP(current_drive->sbp_audsiz); | ||
4240 | |||
4241 | case CDROMREADAUDIO: | ||
4242 | { /* start of CDROMREADAUDIO */ | ||
4243 | int i=0, j=0, frame, block=0; | ||
4244 | u_int try=0; | ||
4245 | u_long timeout; | ||
4246 | u_char *p; | ||
4247 | u_int data_tries = 0; | ||
4248 | u_int data_waits = 0; | ||
4249 | u_int data_retrying = 0; | ||
4250 | int status_tries; | ||
4251 | int error_flag; | ||
4252 | |||
4253 | msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n"); | ||
4254 | if (fam0_drive) RETURN_UP(-EINVAL); | ||
4255 | if (famL_drive) RETURN_UP(-EINVAL); | ||
4256 | if (famV_drive) RETURN_UP(-EINVAL); | ||
4257 | if (famT_drive) RETURN_UP(-EINVAL); | ||
4258 | #ifdef SAFE_MIXED | ||
4259 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
4260 | #endif /* SAFE_MIXED */ | ||
4261 | if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL); | ||
4262 | if (copy_from_user(&read_audio, (void __user *)arg, | ||
4263 | sizeof(struct cdrom_read_audio))) | ||
4264 | RETURN_UP(-EFAULT); | ||
4265 | if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL); | ||
4266 | if (!access_ok(VERIFY_WRITE, read_audio.buf, | ||
4267 | read_audio.nframes*CD_FRAMESIZE_RAW)) | ||
4268 | RETURN_UP(-EFAULT); | ||
4269 | |||
4270 | if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */ | ||
4271 | block=msf2lba(&read_audio.addr.msf.minute); | ||
4272 | else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */ | ||
4273 | block=read_audio.addr.lba; | ||
4274 | else RETURN_UP(-EINVAL); | ||
4275 | #if 000 | ||
4276 | i=cc_SetSpeed(speed_150,0,0); | ||
4277 | if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i); | ||
4278 | #endif | ||
4279 | msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n", | ||
4280 | block, blk2msf(block)); | ||
4281 | msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n"); | ||
4282 | #if OLD_BUSY | ||
4283 | while (busy_data) sbp_sleep(HZ/10); /* wait a bit */ | ||
4284 | busy_audio=1; | ||
4285 | #endif /* OLD_BUSY */ | ||
4286 | error_flag=0; | ||
4287 | for (data_tries=5; data_tries>0; data_tries--) | ||
4288 | { | ||
4289 | msg(DBG_AUD,"data_tries=%d ...\n", data_tries); | ||
4290 | current_drive->mode=READ_AU; | ||
4291 | cc_ModeSelect(CD_FRAMESIZE_RAW); | ||
4292 | cc_ModeSense(); | ||
4293 | for (status_tries=3; status_tries > 0; status_tries--) | ||
4294 | { | ||
4295 | flags_cmd_out |= f_respo3; | ||
4296 | cc_ReadStatus(); | ||
4297 | if (sbp_status() != 0) break; | ||
4298 | if (st_check) cc_ReadError(); | ||
4299 | sbp_sleep(1); /* wait a bit, try again */ | ||
4300 | } | ||
4301 | if (status_tries == 0) | ||
4302 | { | ||
4303 | msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__); | ||
4304 | continue; | ||
4305 | } | ||
4306 | msg(DBG_AUD,"read_audio: sbp_status: ok.\n"); | ||
4307 | |||
4308 | flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; | ||
4309 | if (fam0L_drive) | ||
4310 | { | ||
4311 | flags_cmd_out |= f_lopsta | f_getsta | f_bit1; | ||
4312 | cmd_type=READ_M2; | ||
4313 | drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ | ||
4314 | drvcmd[1]=(block>>16)&0x000000ff; | ||
4315 | drvcmd[2]=(block>>8)&0x000000ff; | ||
4316 | drvcmd[3]=block&0x000000ff; | ||
4317 | drvcmd[4]=0; | ||
4318 | drvcmd[5]=read_audio.nframes; /* # of frames */ | ||
4319 | drvcmd[6]=0; | ||
4320 | } | ||
4321 | else if (fam1_drive) | ||
4322 | { | ||
4323 | drvcmd[0]=CMD1_READ; /* "read frames", new drives */ | ||
4324 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
4325 | drvcmd[4]=0; | ||
4326 | drvcmd[5]=0; | ||
4327 | drvcmd[6]=read_audio.nframes; /* # of frames */ | ||
4328 | } | ||
4329 | else if (fam2_drive) | ||
4330 | { | ||
4331 | drvcmd[0]=CMD2_READ_XA2; | ||
4332 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
4333 | drvcmd[4]=0; | ||
4334 | drvcmd[5]=read_audio.nframes; /* # of frames */ | ||
4335 | drvcmd[6]=0x11; /* raw mode */ | ||
4336 | } | ||
4337 | else if (famT_drive) /* CD-55A: not tested yet */ | ||
4338 | { | ||
4339 | } | ||
4340 | msg(DBG_AUD,"read_audio: before giving \"read\" command.\n"); | ||
4341 | flags_cmd_out=f_putcmd; | ||
4342 | response_count=0; | ||
4343 | i=cmd_out(); | ||
4344 | if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i); | ||
4345 | sbp_sleep(0); | ||
4346 | msg(DBG_AUD,"read_audio: after giving \"read\" command.\n"); | ||
4347 | for (frame=1;frame<2 && !error_flag; frame++) | ||
4348 | { | ||
4349 | try=maxtim_data; | ||
4350 | for (timeout=jiffies+9*HZ; ; ) | ||
4351 | { | ||
4352 | for ( ; try!=0;try--) | ||
4353 | { | ||
4354 | j=inb(CDi_status); | ||
4355 | if (!(j&s_not_data_ready)) break; | ||
4356 | if (!(j&s_not_result_ready)) break; | ||
4357 | if (fam0L_drive) if (j&s_attention) break; | ||
4358 | } | ||
4359 | if (try != 0 || time_after_eq(jiffies, timeout)) break; | ||
4360 | if (data_retrying == 0) data_waits++; | ||
4361 | data_retrying = 1; | ||
4362 | sbp_sleep(1); | ||
4363 | try = 1; | ||
4364 | } | ||
4365 | if (try==0) | ||
4366 | { | ||
4367 | msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n"); | ||
4368 | error_flag++; | ||
4369 | break; | ||
4370 | } | ||
4371 | msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n"); | ||
4372 | if (j&s_not_data_ready) | ||
4373 | { | ||
4374 | msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n"); | ||
4375 | error_flag++; | ||
4376 | break; | ||
4377 | } | ||
4378 | msg(DBG_AUD,"read_audio: before reading data.\n"); | ||
4379 | error_flag=0; | ||
4380 | p = current_drive->aud_buf; | ||
4381 | if (sbpro_type==1) OUT(CDo_sel_i_d,1); | ||
4382 | if (do_16bit) | ||
4383 | { | ||
4384 | u_short *p2 = (u_short *) p; | ||
4385 | |||
4386 | for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) | ||
4387 | { | ||
4388 | if ((inb_p(CDi_status)&s_not_data_ready)) continue; | ||
4389 | |||
4390 | /* get one sample */ | ||
4391 | *p2++ = inw_p(CDi_data); | ||
4392 | *p2++ = inw_p(CDi_data); | ||
4393 | } | ||
4394 | } else { | ||
4395 | for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) | ||
4396 | { | ||
4397 | if ((inb_p(CDi_status)&s_not_data_ready)) continue; | ||
4398 | |||
4399 | /* get one sample */ | ||
4400 | *p++ = inb_p(CDi_data); | ||
4401 | *p++ = inb_p(CDi_data); | ||
4402 | *p++ = inb_p(CDi_data); | ||
4403 | *p++ = inb_p(CDi_data); | ||
4404 | } | ||
4405 | } | ||
4406 | if (sbpro_type==1) OUT(CDo_sel_i_d,0); | ||
4407 | data_retrying = 0; | ||
4408 | } | ||
4409 | msg(DBG_AUD,"read_audio: after reading data.\n"); | ||
4410 | if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ | ||
4411 | { | ||
4412 | msg(DBG_AUD,"read_audio: read aborted by drive\n"); | ||
4413 | #if 0000 | ||
4414 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
4415 | #else | ||
4416 | i=cc_ReadError(); | ||
4417 | #endif | ||
4418 | continue; | ||
4419 | } | ||
4420 | if (fam0L_drive) | ||
4421 | { | ||
4422 | i=maxtim_data; | ||
4423 | for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--) | ||
4424 | { | ||
4425 | for ( ;i!=0;i--) | ||
4426 | { | ||
4427 | j=inb(CDi_status); | ||
4428 | if (!(j&s_not_data_ready)) break; | ||
4429 | if (!(j&s_not_result_ready)) break; | ||
4430 | if (j&s_attention) break; | ||
4431 | } | ||
4432 | if (i != 0 || time_after_eq(jiffies, timeout)) break; | ||
4433 | sbp_sleep(0); | ||
4434 | i = 1; | ||
4435 | } | ||
4436 | if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ"); | ||
4437 | if (!(j&s_attention)) | ||
4438 | { | ||
4439 | msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n"); | ||
4440 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
4441 | continue; | ||
4442 | } | ||
4443 | } | ||
4444 | do | ||
4445 | { | ||
4446 | if (fam0L_drive) cc_ReadStatus(); | ||
4447 | i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ | ||
4448 | if (i<0) { msg(DBG_AUD, | ||
4449 | "read_audio: cc_ReadStatus error after read: %02X\n", | ||
4450 | current_drive->status_bits); | ||
4451 | continue; /* FIXME */ | ||
4452 | } | ||
4453 | } | ||
4454 | while ((fam0L_drive)&&(!st_check)&&(!(i&p_success))); | ||
4455 | if (st_check) | ||
4456 | { | ||
4457 | i=cc_ReadError(); | ||
4458 | msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i); | ||
4459 | continue; | ||
4460 | } | ||
4461 | if (copy_to_user(read_audio.buf, | ||
4462 | current_drive->aud_buf, | ||
4463 | read_audio.nframes * CD_FRAMESIZE_RAW)) | ||
4464 | RETURN_UP(-EFAULT); | ||
4465 | msg(DBG_AUD,"read_audio: copy_to_user done.\n"); | ||
4466 | break; | ||
4467 | } | ||
4468 | cc_ModeSelect(CD_FRAMESIZE); | ||
4469 | cc_ModeSense(); | ||
4470 | current_drive->mode=READ_M1; | ||
4471 | #if OLD_BUSY | ||
4472 | busy_audio=0; | ||
4473 | #endif /* OLD_BUSY */ | ||
4474 | if (data_tries == 0) | ||
4475 | { | ||
4476 | msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__); | ||
4477 | RETURN_UP(-EIO); | ||
4478 | } | ||
4479 | msg(DBG_AUD,"read_audio: successful return.\n"); | ||
4480 | RETURN_UP(0); | ||
4481 | } /* end of CDROMREADAUDIO */ | ||
4482 | |||
4483 | default: | ||
4484 | msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); | ||
4485 | RETURN_UP(-EINVAL); | ||
4486 | } /* end switch(cmd) */ | ||
4487 | } | ||
4488 | |||
4489 | static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | 4169 | static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, |
4490 | void * arg) | 4170 | void * arg) |
4491 | { | 4171 | { |
@@ -4530,7 +4210,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | |||
4530 | default: | 4210 | default: |
4531 | RETURN_UP(-EINVAL); | 4211 | RETURN_UP(-EINVAL); |
4532 | } | 4212 | } |
4533 | 4213 | ||
4534 | case CDROMRESUME: /* resume paused audio play */ | 4214 | case CDROMRESUME: /* resume paused audio play */ |
4535 | msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n"); | 4215 | msg(DBG_IOC,"ioctl: CDROMRESUME entered.\n"); |
4536 | /* resume playing audio tracks when a previous PLAY AUDIO call has */ | 4216 | /* resume playing audio tracks when a previous PLAY AUDIO call has */ |
@@ -4544,12 +4224,12 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | |||
4544 | if (i<0) RETURN_UP(-EIO); | 4224 | if (i<0) RETURN_UP(-EIO); |
4545 | current_drive->audio_state=audio_playing; | 4225 | current_drive->audio_state=audio_playing; |
4546 | RETURN_UP(0); | 4226 | RETURN_UP(0); |
4547 | 4227 | ||
4548 | case CDROMPLAYMSF: | 4228 | case CDROMPLAYMSF: |
4549 | msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); | 4229 | msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n"); |
4550 | #ifdef SAFE_MIXED | 4230 | #ifdef SAFE_MIXED |
4551 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | 4231 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); |
4552 | #endif /* SAFE_MIXED */ | 4232 | #endif /* SAFE_MIXED */ |
4553 | if (current_drive->audio_state==audio_playing) | 4233 | if (current_drive->audio_state==audio_playing) |
4554 | { | 4234 | { |
4555 | i=cc_Pause_Resume(1); | 4235 | i=cc_Pause_Resume(1); |
@@ -4584,7 +4264,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | |||
4584 | msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); | 4264 | msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n"); |
4585 | #ifdef SAFE_MIXED | 4265 | #ifdef SAFE_MIXED |
4586 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | 4266 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); |
4587 | #endif /* SAFE_MIXED */ | 4267 | #endif /* SAFE_MIXED */ |
4588 | if (current_drive->audio_state==audio_playing) | 4268 | if (current_drive->audio_state==audio_playing) |
4589 | { | 4269 | { |
4590 | msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); | 4270 | msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n"); |
@@ -4654,13 +4334,13 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | |||
4654 | cc_DriveReset(); | 4334 | cc_DriveReset(); |
4655 | #endif | 4335 | #endif |
4656 | RETURN_UP(i); | 4336 | RETURN_UP(i); |
4657 | 4337 | ||
4658 | case CDROMSTART: /* Spin up the drive */ | 4338 | case CDROMSTART: /* Spin up the drive */ |
4659 | msg(DBG_IOC,"ioctl: CDROMSTART entered.\n"); | 4339 | msg(DBG_IOC,"ioctl: CDROMSTART entered.\n"); |
4660 | cc_SpinUp(); | 4340 | cc_SpinUp(); |
4661 | current_drive->audio_state=0; | 4341 | current_drive->audio_state=0; |
4662 | RETURN_UP(0); | 4342 | RETURN_UP(0); |
4663 | 4343 | ||
4664 | case CDROMVOLCTRL: /* Volume control */ | 4344 | case CDROMVOLCTRL: /* Volume control */ |
4665 | msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n"); | 4345 | msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n"); |
4666 | memcpy(&volctrl,(char *) arg,sizeof(volctrl)); | 4346 | memcpy(&volctrl,(char *) arg,sizeof(volctrl)); |
@@ -4670,7 +4350,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | |||
4670 | current_drive->vol_ctrl1=volctrl.channel1; | 4350 | current_drive->vol_ctrl1=volctrl.channel1; |
4671 | i=cc_SetVolume(); | 4351 | i=cc_SetVolume(); |
4672 | RETURN_UP(0); | 4352 | RETURN_UP(0); |
4673 | 4353 | ||
4674 | case CDROMVOLREAD: /* read Volume settings from drive */ | 4354 | case CDROMVOLREAD: /* read Volume settings from drive */ |
4675 | msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); | 4355 | msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); |
4676 | st=cc_GetVolume(); | 4356 | st=cc_GetVolume(); |
@@ -4694,7 +4374,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | |||
4694 | if (i<0) { | 4374 | if (i<0) { |
4695 | j=cc_ReadError(); /* clear out error status from drive */ | 4375 | j=cc_ReadError(); /* clear out error status from drive */ |
4696 | current_drive->audio_state=CDROM_AUDIO_NO_STATUS; | 4376 | current_drive->audio_state=CDROM_AUDIO_NO_STATUS; |
4697 | /* get and set the disk state here, | 4377 | /* get and set the disk state here, |
4698 | probably not the right place, but who cares! | 4378 | probably not the right place, but who cares! |
4699 | It makes it work properly! --AJK */ | 4379 | It makes it work properly! --AJK */ |
4700 | if (current_drive->CD_changed==0xFF) { | 4380 | if (current_drive->CD_changed==0xFF) { |
@@ -4715,8 +4395,8 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | |||
4715 | } | 4395 | } |
4716 | } | 4396 | } |
4717 | memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); | 4397 | memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); |
4718 | /* | 4398 | /* |
4719 | This virtual crap is very bogus! | 4399 | This virtual crap is very bogus! |
4720 | It doesn't detect when the cd is done playing audio! | 4400 | It doesn't detect when the cd is done playing audio! |
4721 | Lets do this right with proper hardware register reading! | 4401 | Lets do this right with proper hardware register reading! |
4722 | */ | 4402 | */ |
@@ -4775,7 +4455,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | |||
4775 | SC.cdsc_trk,SC.cdsc_ind, | 4455 | SC.cdsc_trk,SC.cdsc_ind, |
4776 | SC.cdsc_absaddr,SC.cdsc_reladdr); | 4456 | SC.cdsc_absaddr,SC.cdsc_reladdr); |
4777 | RETURN_UP(0); | 4457 | RETURN_UP(0); |
4778 | 4458 | ||
4779 | default: | 4459 | default: |
4780 | msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); | 4460 | msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); |
4781 | RETURN_UP(-EINVAL); | 4461 | RETURN_UP(-EINVAL); |
@@ -4788,7 +4468,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, | |||
4788 | static void sbp_transfer(struct request *req) | 4468 | static void sbp_transfer(struct request *req) |
4789 | { | 4469 | { |
4790 | long offs; | 4470 | long offs; |
4791 | 4471 | ||
4792 | while ( (req->nr_sectors > 0) && | 4472 | while ( (req->nr_sectors > 0) && |
4793 | (req->sector/4 >= current_drive->sbp_first_frame) && | 4473 | (req->sector/4 >= current_drive->sbp_first_frame) && |
4794 | (req->sector/4 <= current_drive->sbp_last_frame) ) | 4474 | (req->sector/4 <= current_drive->sbp_last_frame) ) |
@@ -4807,11 +4487,11 @@ static void sbp_transfer(struct request *req) | |||
4807 | * | 4487 | * |
4808 | * This is a kludge so we don't need to modify end_request. | 4488 | * This is a kludge so we don't need to modify end_request. |
4809 | * We put the req we take out after INIT_REQUEST in the requests list, | 4489 | * We put the req we take out after INIT_REQUEST in the requests list, |
4810 | * so that end_request will discard it. | 4490 | * so that end_request will discard it. |
4811 | * | 4491 | * |
4812 | * The bug could be present in other block devices, perhaps we | 4492 | * The bug could be present in other block devices, perhaps we |
4813 | * should modify INIT_REQUEST and end_request instead, and | 4493 | * should modify INIT_REQUEST and end_request instead, and |
4814 | * change every block device.. | 4494 | * change every block device.. |
4815 | * | 4495 | * |
4816 | * Could be a race here?? Could e.g. a timer interrupt schedule() us? | 4496 | * Could be a race here?? Could e.g. a timer interrupt schedule() us? |
4817 | * If so, we should copy end_request here, and do it right.. (or | 4497 | * If so, we should copy end_request here, and do it right.. (or |
@@ -4883,19 +4563,19 @@ static void do_sbpcd_request(request_queue_t * q) | |||
4883 | while (busy_audio) sbp_sleep(HZ); /* wait a bit */ | 4563 | while (busy_audio) sbp_sleep(HZ); /* wait a bit */ |
4884 | busy_data=1; | 4564 | busy_data=1; |
4885 | #endif /* OLD_BUSY */ | 4565 | #endif /* OLD_BUSY */ |
4886 | 4566 | ||
4887 | if (p->audio_state==audio_playing) goto err_done; | 4567 | if (p->audio_state==audio_playing) goto err_done; |
4888 | if (p != current_drive) | 4568 | if (p != current_drive) |
4889 | switch_drive(p); | 4569 | switch_drive(p); |
4890 | 4570 | ||
4891 | block = req->sector; /* always numbered as 512-byte-pieces */ | 4571 | block = req->sector; /* always numbered as 512-byte-pieces */ |
4892 | nsect = req->nr_sectors; /* always counted as 512-byte-pieces */ | 4572 | nsect = req->nr_sectors; /* always counted as 512-byte-pieces */ |
4893 | 4573 | ||
4894 | msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect); | 4574 | msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect); |
4895 | #if 0 | 4575 | #if 0 |
4896 | msg(DBG_MUL,"read LBA %d\n", block/4); | 4576 | msg(DBG_MUL,"read LBA %d\n", block/4); |
4897 | #endif | 4577 | #endif |
4898 | 4578 | ||
4899 | sbp_transfer(req); | 4579 | sbp_transfer(req); |
4900 | /* if we satisfied the request from the buffer, we're done. */ | 4580 | /* if we satisfied the request from the buffer, we're done. */ |
4901 | if (req->nr_sectors == 0) | 4581 | if (req->nr_sectors == 0) |
@@ -4914,10 +4594,10 @@ static void do_sbpcd_request(request_queue_t * q) | |||
4914 | i=prepare(0,0); /* at moment not really a hassle check, but ... */ | 4594 | i=prepare(0,0); /* at moment not really a hassle check, but ... */ |
4915 | if (i!=0) | 4595 | if (i!=0) |
4916 | msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i); | 4596 | msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i); |
4917 | #endif /* FUTURE */ | 4597 | #endif /* FUTURE */ |
4918 | 4598 | ||
4919 | if (!st_spinning) cc_SpinUp(); | 4599 | if (!st_spinning) cc_SpinUp(); |
4920 | 4600 | ||
4921 | for (data_tries=n_retries; data_tries > 0; data_tries--) | 4601 | for (data_tries=n_retries; data_tries > 0; data_tries--) |
4922 | { | 4602 | { |
4923 | for (status_tries=3; status_tries > 0; status_tries--) | 4603 | for (status_tries=3; status_tries > 0; status_tries--) |
@@ -4940,7 +4620,7 @@ static void do_sbpcd_request(request_queue_t * q) | |||
4940 | { | 4620 | { |
4941 | #ifdef SAFE_MIXED | 4621 | #ifdef SAFE_MIXED |
4942 | current_drive->has_data=2; /* is really a data disk */ | 4622 | current_drive->has_data=2; /* is really a data disk */ |
4943 | #endif /* SAFE_MIXED */ | 4623 | #endif /* SAFE_MIXED */ |
4944 | #ifdef DEBUG_GTL | 4624 | #ifdef DEBUG_GTL |
4945 | printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n", | 4625 | printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n", |
4946 | xnr, req, req->sector, req->nr_sectors, jiffies); | 4626 | xnr, req, req->sector, req->nr_sectors, jiffies); |
@@ -4951,7 +4631,7 @@ static void do_sbpcd_request(request_queue_t * q) | |||
4951 | goto request_loop; | 4631 | goto request_loop; |
4952 | } | 4632 | } |
4953 | } | 4633 | } |
4954 | 4634 | ||
4955 | err_done: | 4635 | err_done: |
4956 | #if OLD_BUSY | 4636 | #if OLD_BUSY |
4957 | busy_data=0; | 4637 | busy_data=0; |
@@ -4976,7 +4656,7 @@ static void sbp_read_cmd(struct request *req) | |||
4976 | 4656 | ||
4977 | int i; | 4657 | int i; |
4978 | int block; | 4658 | int block; |
4979 | 4659 | ||
4980 | current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ | 4660 | current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ |
4981 | current_drive->sbp_current = 0; | 4661 | current_drive->sbp_current = 0; |
4982 | block=req->sector/4; | 4662 | block=req->sector/4; |
@@ -4993,7 +4673,7 @@ static void sbp_read_cmd(struct request *req) | |||
4993 | current_drive->sbp_read_frames=1; | 4673 | current_drive->sbp_read_frames=1; |
4994 | } | 4674 | } |
4995 | } | 4675 | } |
4996 | 4676 | ||
4997 | flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; | 4677 | flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; |
4998 | clr_cmdbuf(); | 4678 | clr_cmdbuf(); |
4999 | if (famV_drive) | 4679 | if (famV_drive) |
@@ -5092,7 +4772,7 @@ static int sbp_data(struct request *req) | |||
5092 | int success; | 4772 | int success; |
5093 | int wait; | 4773 | int wait; |
5094 | int duration; | 4774 | int duration; |
5095 | 4775 | ||
5096 | error_flag=0; | 4776 | error_flag=0; |
5097 | success=0; | 4777 | success=0; |
5098 | #if LONG_TIMING | 4778 | #if LONG_TIMING |
@@ -5105,12 +4785,12 @@ static int sbp_data(struct request *req) | |||
5105 | for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++) | 4785 | for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++) |
5106 | { | 4786 | { |
5107 | SBPCD_CLI; | 4787 | SBPCD_CLI; |
5108 | 4788 | ||
5109 | del_timer(&data_timer); | 4789 | del_timer(&data_timer); |
5110 | data_timer.expires=jiffies+max_latency; | 4790 | data_timer.expires=jiffies+max_latency; |
5111 | timed_out_data=0; | 4791 | timed_out_data=0; |
5112 | add_timer(&data_timer); | 4792 | add_timer(&data_timer); |
5113 | while (!timed_out_data) | 4793 | while (!timed_out_data) |
5114 | { | 4794 | { |
5115 | if (current_drive->f_multisession) try=maxtim_data*4; | 4795 | if (current_drive->f_multisession) try=maxtim_data*4; |
5116 | else try=maxtim_data; | 4796 | else try=maxtim_data; |
@@ -5207,9 +4887,9 @@ static int sbp_data(struct request *req) | |||
5207 | else | 4887 | else |
5208 | { | 4888 | { |
5209 | sbp_sleep(1); | 4889 | sbp_sleep(1); |
5210 | OUT(CDo_sel_i_d,0); | 4890 | OUT(CDo_sel_i_d,0); |
5211 | i=inb(CDi_status); | 4891 | i=inb(CDi_status); |
5212 | } | 4892 | } |
5213 | if (!(i&s_not_data_ready)) | 4893 | if (!(i&s_not_data_ready)) |
5214 | { | 4894 | { |
5215 | OUT(CDo_sel_i_d,1); | 4895 | OUT(CDo_sel_i_d,1); |
@@ -5311,7 +4991,7 @@ static int sbp_data(struct request *req) | |||
5311 | } | 4991 | } |
5312 | SBPCD_STI; | 4992 | SBPCD_STI; |
5313 | } | 4993 | } |
5314 | 4994 | ||
5315 | #if 0 | 4995 | #if 0 |
5316 | if (!success) | 4996 | if (!success) |
5317 | #endif | 4997 | #endif |
@@ -5370,7 +5050,326 @@ static int sbpcd_block_ioctl(struct inode *inode, struct file *file, | |||
5370 | unsigned cmd, unsigned long arg) | 5050 | unsigned cmd, unsigned long arg) |
5371 | { | 5051 | { |
5372 | struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; | 5052 | struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; |
5373 | return cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg); | 5053 | struct cdrom_device_info *cdi = p->sbpcd_infop; |
5054 | int ret, i; | ||
5055 | |||
5056 | ret = cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg); | ||
5057 | if (ret != -ENOSYS) | ||
5058 | return ret; | ||
5059 | |||
5060 | msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg); | ||
5061 | if (p->drv_id==-1) { | ||
5062 | msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); | ||
5063 | return (-ENXIO); /* no such drive */ | ||
5064 | } | ||
5065 | down(&ioctl_read_sem); | ||
5066 | if (p != current_drive) | ||
5067 | switch_drive(p); | ||
5068 | |||
5069 | msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); | ||
5070 | switch (cmd) /* Sun-compatible */ | ||
5071 | { | ||
5072 | case DDIOCSDBG: /* DDI Debug */ | ||
5073 | if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM); | ||
5074 | i=sbpcd_dbg_ioctl(arg,1); | ||
5075 | RETURN_UP(i); | ||
5076 | case CDROMRESET: /* hard reset the drive */ | ||
5077 | msg(DBG_IOC,"ioctl: CDROMRESET entered.\n"); | ||
5078 | i=DriveReset(); | ||
5079 | current_drive->audio_state=0; | ||
5080 | RETURN_UP(i); | ||
5081 | |||
5082 | case CDROMREADMODE1: | ||
5083 | msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); | ||
5084 | #ifdef SAFE_MIXED | ||
5085 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
5086 | #endif /* SAFE_MIXED */ | ||
5087 | cc_ModeSelect(CD_FRAMESIZE); | ||
5088 | cc_ModeSense(); | ||
5089 | current_drive->mode=READ_M1; | ||
5090 | RETURN_UP(0); | ||
5091 | |||
5092 | case CDROMREADMODE2: /* not usable at the moment */ | ||
5093 | msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); | ||
5094 | #ifdef SAFE_MIXED | ||
5095 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
5096 | #endif /* SAFE_MIXED */ | ||
5097 | cc_ModeSelect(CD_FRAMESIZE_RAW1); | ||
5098 | cc_ModeSense(); | ||
5099 | current_drive->mode=READ_M2; | ||
5100 | RETURN_UP(0); | ||
5101 | |||
5102 | case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */ | ||
5103 | msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n"); | ||
5104 | if (current_drive->sbp_audsiz>0) | ||
5105 | vfree(current_drive->aud_buf); | ||
5106 | current_drive->aud_buf=NULL; | ||
5107 | current_drive->sbp_audsiz=arg; | ||
5108 | |||
5109 | if (current_drive->sbp_audsiz>16) | ||
5110 | { | ||
5111 | current_drive->sbp_audsiz = 0; | ||
5112 | RETURN_UP(current_drive->sbp_audsiz); | ||
5113 | } | ||
5114 | |||
5115 | if (current_drive->sbp_audsiz>0) | ||
5116 | { | ||
5117 | current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW); | ||
5118 | if (current_drive->aud_buf==NULL) | ||
5119 | { | ||
5120 | msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz); | ||
5121 | current_drive->sbp_audsiz=0; | ||
5122 | } | ||
5123 | else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz); | ||
5124 | } | ||
5125 | RETURN_UP(current_drive->sbp_audsiz); | ||
5126 | |||
5127 | case CDROMREADAUDIO: | ||
5128 | { /* start of CDROMREADAUDIO */ | ||
5129 | int i=0, j=0, frame, block=0; | ||
5130 | u_int try=0; | ||
5131 | u_long timeout; | ||
5132 | u_char *p; | ||
5133 | u_int data_tries = 0; | ||
5134 | u_int data_waits = 0; | ||
5135 | u_int data_retrying = 0; | ||
5136 | int status_tries; | ||
5137 | int error_flag; | ||
5138 | |||
5139 | msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n"); | ||
5140 | if (fam0_drive) RETURN_UP(-EINVAL); | ||
5141 | if (famL_drive) RETURN_UP(-EINVAL); | ||
5142 | if (famV_drive) RETURN_UP(-EINVAL); | ||
5143 | if (famT_drive) RETURN_UP(-EINVAL); | ||
5144 | #ifdef SAFE_MIXED | ||
5145 | if (current_drive->has_data>1) RETURN_UP(-EBUSY); | ||
5146 | #endif /* SAFE_MIXED */ | ||
5147 | if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL); | ||
5148 | if (copy_from_user(&read_audio, (void __user *)arg, | ||
5149 | sizeof(struct cdrom_read_audio))) | ||
5150 | RETURN_UP(-EFAULT); | ||
5151 | if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL); | ||
5152 | if (!access_ok(VERIFY_WRITE, read_audio.buf, | ||
5153 | read_audio.nframes*CD_FRAMESIZE_RAW)) | ||
5154 | RETURN_UP(-EFAULT); | ||
5155 | |||
5156 | if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */ | ||
5157 | block=msf2lba(&read_audio.addr.msf.minute); | ||
5158 | else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */ | ||
5159 | block=read_audio.addr.lba; | ||
5160 | else RETURN_UP(-EINVAL); | ||
5161 | #if 000 | ||
5162 | i=cc_SetSpeed(speed_150,0,0); | ||
5163 | if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i); | ||
5164 | #endif | ||
5165 | msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n", | ||
5166 | block, blk2msf(block)); | ||
5167 | msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n"); | ||
5168 | #if OLD_BUSY | ||
5169 | while (busy_data) sbp_sleep(HZ/10); /* wait a bit */ | ||
5170 | busy_audio=1; | ||
5171 | #endif /* OLD_BUSY */ | ||
5172 | error_flag=0; | ||
5173 | for (data_tries=5; data_tries>0; data_tries--) | ||
5174 | { | ||
5175 | msg(DBG_AUD,"data_tries=%d ...\n", data_tries); | ||
5176 | current_drive->mode=READ_AU; | ||
5177 | cc_ModeSelect(CD_FRAMESIZE_RAW); | ||
5178 | cc_ModeSense(); | ||
5179 | for (status_tries=3; status_tries > 0; status_tries--) | ||
5180 | { | ||
5181 | flags_cmd_out |= f_respo3; | ||
5182 | cc_ReadStatus(); | ||
5183 | if (sbp_status() != 0) break; | ||
5184 | if (st_check) cc_ReadError(); | ||
5185 | sbp_sleep(1); /* wait a bit, try again */ | ||
5186 | } | ||
5187 | if (status_tries == 0) | ||
5188 | { | ||
5189 | msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__); | ||
5190 | continue; | ||
5191 | } | ||
5192 | msg(DBG_AUD,"read_audio: sbp_status: ok.\n"); | ||
5193 | |||
5194 | flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; | ||
5195 | if (fam0L_drive) | ||
5196 | { | ||
5197 | flags_cmd_out |= f_lopsta | f_getsta | f_bit1; | ||
5198 | cmd_type=READ_M2; | ||
5199 | drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ | ||
5200 | drvcmd[1]=(block>>16)&0x000000ff; | ||
5201 | drvcmd[2]=(block>>8)&0x000000ff; | ||
5202 | drvcmd[3]=block&0x000000ff; | ||
5203 | drvcmd[4]=0; | ||
5204 | drvcmd[5]=read_audio.nframes; /* # of frames */ | ||
5205 | drvcmd[6]=0; | ||
5206 | } | ||
5207 | else if (fam1_drive) | ||
5208 | { | ||
5209 | drvcmd[0]=CMD1_READ; /* "read frames", new drives */ | ||
5210 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
5211 | drvcmd[4]=0; | ||
5212 | drvcmd[5]=0; | ||
5213 | drvcmd[6]=read_audio.nframes; /* # of frames */ | ||
5214 | } | ||
5215 | else if (fam2_drive) | ||
5216 | { | ||
5217 | drvcmd[0]=CMD2_READ_XA2; | ||
5218 | lba2msf(block,&drvcmd[1]); /* msf-bin format required */ | ||
5219 | drvcmd[4]=0; | ||
5220 | drvcmd[5]=read_audio.nframes; /* # of frames */ | ||
5221 | drvcmd[6]=0x11; /* raw mode */ | ||
5222 | } | ||
5223 | else if (famT_drive) /* CD-55A: not tested yet */ | ||
5224 | { | ||
5225 | } | ||
5226 | msg(DBG_AUD,"read_audio: before giving \"read\" command.\n"); | ||
5227 | flags_cmd_out=f_putcmd; | ||
5228 | response_count=0; | ||
5229 | i=cmd_out(); | ||
5230 | if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i); | ||
5231 | sbp_sleep(0); | ||
5232 | msg(DBG_AUD,"read_audio: after giving \"read\" command.\n"); | ||
5233 | for (frame=1;frame<2 && !error_flag; frame++) | ||
5234 | { | ||
5235 | try=maxtim_data; | ||
5236 | for (timeout=jiffies+9*HZ; ; ) | ||
5237 | { | ||
5238 | for ( ; try!=0;try--) | ||
5239 | { | ||
5240 | j=inb(CDi_status); | ||
5241 | if (!(j&s_not_data_ready)) break; | ||
5242 | if (!(j&s_not_result_ready)) break; | ||
5243 | if (fam0L_drive) if (j&s_attention) break; | ||
5244 | } | ||
5245 | if (try != 0 || time_after_eq(jiffies, timeout)) break; | ||
5246 | if (data_retrying == 0) data_waits++; | ||
5247 | data_retrying = 1; | ||
5248 | sbp_sleep(1); | ||
5249 | try = 1; | ||
5250 | } | ||
5251 | if (try==0) | ||
5252 | { | ||
5253 | msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n"); | ||
5254 | error_flag++; | ||
5255 | break; | ||
5256 | } | ||
5257 | msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n"); | ||
5258 | if (j&s_not_data_ready) | ||
5259 | { | ||
5260 | msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n"); | ||
5261 | error_flag++; | ||
5262 | break; | ||
5263 | } | ||
5264 | msg(DBG_AUD,"read_audio: before reading data.\n"); | ||
5265 | error_flag=0; | ||
5266 | p = current_drive->aud_buf; | ||
5267 | if (sbpro_type==1) OUT(CDo_sel_i_d,1); | ||
5268 | if (do_16bit) | ||
5269 | { | ||
5270 | u_short *p2 = (u_short *) p; | ||
5271 | |||
5272 | for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) | ||
5273 | { | ||
5274 | if ((inb_p(CDi_status)&s_not_data_ready)) continue; | ||
5275 | |||
5276 | /* get one sample */ | ||
5277 | *p2++ = inw_p(CDi_data); | ||
5278 | *p2++ = inw_p(CDi_data); | ||
5279 | } | ||
5280 | } else { | ||
5281 | for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;) | ||
5282 | { | ||
5283 | if ((inb_p(CDi_status)&s_not_data_ready)) continue; | ||
5284 | |||
5285 | /* get one sample */ | ||
5286 | *p++ = inb_p(CDi_data); | ||
5287 | *p++ = inb_p(CDi_data); | ||
5288 | *p++ = inb_p(CDi_data); | ||
5289 | *p++ = inb_p(CDi_data); | ||
5290 | } | ||
5291 | } | ||
5292 | if (sbpro_type==1) OUT(CDo_sel_i_d,0); | ||
5293 | data_retrying = 0; | ||
5294 | } | ||
5295 | msg(DBG_AUD,"read_audio: after reading data.\n"); | ||
5296 | if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ | ||
5297 | { | ||
5298 | msg(DBG_AUD,"read_audio: read aborted by drive\n"); | ||
5299 | #if 0000 | ||
5300 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
5301 | #else | ||
5302 | i=cc_ReadError(); | ||
5303 | #endif | ||
5304 | continue; | ||
5305 | } | ||
5306 | if (fam0L_drive) | ||
5307 | { | ||
5308 | i=maxtim_data; | ||
5309 | for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--) | ||
5310 | { | ||
5311 | for ( ;i!=0;i--) | ||
5312 | { | ||
5313 | j=inb(CDi_status); | ||
5314 | if (!(j&s_not_data_ready)) break; | ||
5315 | if (!(j&s_not_result_ready)) break; | ||
5316 | if (j&s_attention) break; | ||
5317 | } | ||
5318 | if (i != 0 || time_after_eq(jiffies, timeout)) break; | ||
5319 | sbp_sleep(0); | ||
5320 | i = 1; | ||
5321 | } | ||
5322 | if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ"); | ||
5323 | if (!(j&s_attention)) | ||
5324 | { | ||
5325 | msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n"); | ||
5326 | i=cc_DriveReset(); /* ugly fix to prevent a hang */ | ||
5327 | continue; | ||
5328 | } | ||
5329 | } | ||
5330 | do | ||
5331 | { | ||
5332 | if (fam0L_drive) cc_ReadStatus(); | ||
5333 | i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ | ||
5334 | if (i<0) { msg(DBG_AUD, | ||
5335 | "read_audio: cc_ReadStatus error after read: %02X\n", | ||
5336 | current_drive->status_bits); | ||
5337 | continue; /* FIXME */ | ||
5338 | } | ||
5339 | } | ||
5340 | while ((fam0L_drive)&&(!st_check)&&(!(i&p_success))); | ||
5341 | if (st_check) | ||
5342 | { | ||
5343 | i=cc_ReadError(); | ||
5344 | msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i); | ||
5345 | continue; | ||
5346 | } | ||
5347 | if (copy_to_user(read_audio.buf, | ||
5348 | current_drive->aud_buf, | ||
5349 | read_audio.nframes * CD_FRAMESIZE_RAW)) | ||
5350 | RETURN_UP(-EFAULT); | ||
5351 | msg(DBG_AUD,"read_audio: copy_to_user done.\n"); | ||
5352 | break; | ||
5353 | } | ||
5354 | cc_ModeSelect(CD_FRAMESIZE); | ||
5355 | cc_ModeSense(); | ||
5356 | current_drive->mode=READ_M1; | ||
5357 | #if OLD_BUSY | ||
5358 | busy_audio=0; | ||
5359 | #endif /* OLD_BUSY */ | ||
5360 | if (data_tries == 0) | ||
5361 | { | ||
5362 | msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__); | ||
5363 | RETURN_UP(-EIO); | ||
5364 | } | ||
5365 | msg(DBG_AUD,"read_audio: successful return.\n"); | ||
5366 | RETURN_UP(0); | ||
5367 | } /* end of CDROMREADAUDIO */ | ||
5368 | |||
5369 | default: | ||
5370 | msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); | ||
5371 | RETURN_UP(-EINVAL); | ||
5372 | } /* end switch(cmd) */ | ||
5374 | } | 5373 | } |
5375 | 5374 | ||
5376 | static int sbpcd_block_media_changed(struct gendisk *disk) | 5375 | static int sbpcd_block_media_changed(struct gendisk *disk) |
@@ -5478,10 +5477,9 @@ static struct cdrom_device_ops sbpcd_dops = { | |||
5478 | .get_mcn = sbpcd_get_mcn, | 5477 | .get_mcn = sbpcd_get_mcn, |
5479 | .reset = sbpcd_reset, | 5478 | .reset = sbpcd_reset, |
5480 | .audio_ioctl = sbpcd_audio_ioctl, | 5479 | .audio_ioctl = sbpcd_audio_ioctl, |
5481 | .dev_ioctl = sbpcd_dev_ioctl, | ||
5482 | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | | 5480 | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | |
5483 | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | | 5481 | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | |
5484 | CDC_MCN | CDC_PLAY_AUDIO | CDC_IOCTLS, | 5482 | CDC_MCN | CDC_PLAY_AUDIO, |
5485 | .n_minors = 1, | 5483 | .n_minors = 1, |
5486 | }; | 5484 | }; |
5487 | 5485 | ||
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index e27617259552..c0f817ba7adb 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c | |||
@@ -627,7 +627,7 @@ static struct cdrom_device_ops viocd_dops = { | |||
627 | .media_changed = viocd_media_changed, | 627 | .media_changed = viocd_media_changed, |
628 | .lock_door = viocd_lock_door, | 628 | .lock_door = viocd_lock_door, |
629 | .generic_packet = viocd_packet, | 629 | .generic_packet = viocd_packet, |
630 | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM | 630 | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM |
631 | }; | 631 | }; |
632 | 632 | ||
633 | static int __init find_capability(const char *type) | 633 | static int __init find_capability(const char *type) |