summaryrefslogtreecommitdiff
path: root/drivers/cdrom/cdrom.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cdrom/cdrom.c')
-rw-r--r--drivers/cdrom/cdrom.c1281
1 files changed, 643 insertions, 638 deletions
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 8a3aff724d98..2a44767891f5 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -312,36 +312,24 @@ static const char *mrw_format_status[] = {
static const char *mrw_address_space[] = { "DMA", "GAA" };
-#if (ERRLOGMASK!=CD_NOTHING)
-#define cdinfo(type, fmt, args...) \
+#if (ERRLOGMASK != CD_NOTHING)
+#define cd_dbg(type, fmt, ...) \
do { \
if ((ERRLOGMASK & type) || debug == 1) \
- pr_info(fmt, ##args); \
+ pr_debug(fmt, ##__VA_ARGS__); \
} while (0)
#else
-#define cdinfo(type, fmt, args...) \
+#define cd_dbg(type, fmt, ...) \
do { \
if (0 && (ERRLOGMASK & type) || debug == 1) \
- pr_info(fmt, ##args); \
+ pr_debug(fmt, ##__VA_ARGS__); \
} while (0)
#endif
-/* These are used to simplify getting data in from and back to user land */
-#define IOCTL_IN(arg, type, in) \
- if (copy_from_user(&(in), (type __user *) (arg), sizeof (in))) \
- return -EFAULT;
-
-#define IOCTL_OUT(arg, type, out) \
- if (copy_to_user((type __user *) (arg), &(out), sizeof (out))) \
- return -EFAULT;
-
/* The (cdo->capability & ~cdi->mask & CDC_XXX) construct was used in
a lot of places. This macro makes the code more clear. */
#define CDROM_CAN(type) (cdi->ops->capability & ~cdi->mask & (type))
-/* used in the audio ioctls */
-#define CHECKAUDIO if ((ret=check_for_audio_disc(cdi, cdo))) return ret
-
/*
* Another popular OS uses 7 seconds as the hard timeout for default
* commands, so it is a good choice for us as well.
@@ -349,21 +337,6 @@ do { \
#define CDROM_DEF_TIMEOUT (7 * HZ)
/* Not-exported routines. */
-static int open_for_data(struct cdrom_device_info * cdi);
-static int check_for_audio_disc(struct cdrom_device_info * cdi,
- struct cdrom_device_ops * cdo);
-static void sanitize_format(union cdrom_addr *addr,
- u_char * curr, u_char requested);
-static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
- unsigned long arg);
-
-int cdrom_get_last_written(struct cdrom_device_info *, long *);
-static int cdrom_get_next_writable(struct cdrom_device_info *, long *);
-static void cdrom_count_tracks(struct cdrom_device_info *, tracktype*);
-
-static int cdrom_mrw_exit(struct cdrom_device_info *cdi);
-
-static int cdrom_get_disc_info(struct cdrom_device_info *cdi, disc_information *di);
static void cdrom_sysctl_register(void);
@@ -382,113 +355,65 @@ static int cdrom_dummy_generic_packet(struct cdrom_device_info *cdi,
return -EIO;
}
-/* This macro makes sure we don't have to check on cdrom_device_ops
- * existence in the run-time routines below. Change_capability is a
- * hack to have the capability flags defined const, while we can still
- * change it here without gcc complaining at every line.
- */
-#define ENSURE(call, bits) if (cdo->call == NULL) *change_capability &= ~(bits)
-
-int register_cdrom(struct cdrom_device_info *cdi)
-{
- static char banner_printed;
- struct cdrom_device_ops *cdo = cdi->ops;
- int *change_capability = (int *)&cdo->capability; /* hack */
-
- cdinfo(CD_OPEN, "entering register_cdrom\n");
-
- if (cdo->open == NULL || cdo->release == NULL)
- return -EINVAL;
- if (!banner_printed) {
- pr_info("Uniform CD-ROM driver " REVISION "\n");
- banner_printed = 1;
- cdrom_sysctl_register();
- }
-
- ENSURE(drive_status, CDC_DRIVE_STATUS );
- if (cdo->check_events == NULL && cdo->media_changed == NULL)
- *change_capability = ~(CDC_MEDIA_CHANGED | CDC_SELECT_DISC);
- ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY);
- ENSURE(lock_door, CDC_LOCK);
- ENSURE(select_speed, CDC_SELECT_SPEED);
- ENSURE(get_last_session, CDC_MULTI_SESSION);
- ENSURE(get_mcn, CDC_MCN);
- ENSURE(reset, CDC_RESET);
- ENSURE(generic_packet, CDC_GENERIC_PACKET);
- cdi->mc_flags = 0;
- cdo->n_minors = 0;
- cdi->options = CDO_USE_FFLAGS;
-
- if (autoclose==1 && CDROM_CAN(CDC_CLOSE_TRAY))
- cdi->options |= (int) CDO_AUTO_CLOSE;
- if (autoeject==1 && CDROM_CAN(CDC_OPEN_TRAY))
- cdi->options |= (int) CDO_AUTO_EJECT;
- if (lockdoor==1)
- cdi->options |= (int) CDO_LOCK;
- if (check_media_type==1)
- cdi->options |= (int) CDO_CHECK_TYPE;
-
- if (CDROM_CAN(CDC_MRW_W))
- cdi->exit = cdrom_mrw_exit;
-
- if (cdi->disk)
- cdi->cdda_method = CDDA_BPC_FULL;
- else
- cdi->cdda_method = CDDA_OLD;
-
- if (!cdo->generic_packet)
- cdo->generic_packet = cdrom_dummy_generic_packet;
-
- cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
- mutex_lock(&cdrom_mutex);
- list_add(&cdi->list, &cdrom_list);
- mutex_unlock(&cdrom_mutex);
- return 0;
-}
-#undef ENSURE
-
-void unregister_cdrom(struct cdrom_device_info *cdi)
+static int cdrom_flush_cache(struct cdrom_device_info *cdi)
{
- cdinfo(CD_OPEN, "entering unregister_cdrom\n");
+ struct packet_command cgc;
- mutex_lock(&cdrom_mutex);
- list_del(&cdi->list);
- mutex_unlock(&cdrom_mutex);
+ init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
+ cgc.cmd[0] = GPCMD_FLUSH_CACHE;
- if (cdi->exit)
- cdi->exit(cdi);
+ cgc.timeout = 5 * 60 * HZ;
- cdi->ops->n_minors--;
- cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
+ return cdi->ops->generic_packet(cdi, &cgc);
}
-int cdrom_get_media_event(struct cdrom_device_info *cdi,
- struct media_event_desc *med)
+/* requires CD R/RW */
+static int cdrom_get_disc_info(struct cdrom_device_info *cdi,
+ disc_information *di)
{
+ struct cdrom_device_ops *cdo = cdi->ops;
struct packet_command cgc;
- unsigned char buffer[8];
- struct event_header *eh = (struct event_header *) buffer;
+ int ret, buflen;
- init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
- cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
- cgc.cmd[1] = 1; /* IMMED */
- cgc.cmd[4] = 1 << 4; /* media event */
- cgc.cmd[8] = sizeof(buffer);
+ /* set up command and get the disc info */
+ init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ);
+ cgc.cmd[0] = GPCMD_READ_DISC_INFO;
+ cgc.cmd[8] = cgc.buflen = 2;
cgc.quiet = 1;
- if (cdi->ops->generic_packet(cdi, &cgc))
- return 1;
+ ret = cdo->generic_packet(cdi, &cgc);
+ if (ret)
+ return ret;
- if (be16_to_cpu(eh->data_len) < sizeof(*med))
- return 1;
+ /* not all drives have the same disc_info length, so requeue
+ * packet with the length the drive tells us it can supply
+ */
+ buflen = be16_to_cpu(di->disc_information_length) +
+ sizeof(di->disc_information_length);
- if (eh->nea || eh->notification_class != 0x4)
- return 1;
+ if (buflen > sizeof(disc_information))
+ buflen = sizeof(disc_information);
- memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
- return 0;
+ cgc.cmd[8] = cgc.buflen = buflen;
+ ret = cdo->generic_packet(cdi, &cgc);
+ if (ret)
+ return ret;
+
+ /* return actual fill size */
+ return buflen;
}
+/* This macro makes sure we don't have to check on cdrom_device_ops
+ * existence in the run-time routines below. Change_capability is a
+ * hack to have the capability flags defined const, while we can still
+ * change it here without gcc complaining at every line.
+ */
+#define ENSURE(call, bits) \
+do { \
+ if (cdo->call == NULL) \
+ *change_capability &= ~(bits); \
+} while (0)
+
/*
* the first prototypes used 0x2c as the page code for the mrw mode page,
* subsequently this was changed to 0x03. probe the one used by this drive
@@ -605,18 +530,6 @@ static int cdrom_mrw_bgformat_susp(struct cdrom_device_info *cdi, int immed)
return cdi->ops->generic_packet(cdi, &cgc);
}
-static int cdrom_flush_cache(struct cdrom_device_info *cdi)
-{
- struct packet_command cgc;
-
- init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
- cgc.cmd[0] = GPCMD_FLUSH_CACHE;
-
- cgc.timeout = 5 * 60 * HZ;
-
- return cdi->ops->generic_packet(cdi, &cgc);
-}
-
static int cdrom_mrw_exit(struct cdrom_device_info *cdi)
{
disc_information di;
@@ -650,17 +563,19 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
cgc.buffer = buffer;
cgc.buflen = sizeof(buffer);
- if ((ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0)))
+ ret = cdrom_mode_sense(cdi, &cgc, cdi->mrw_mode_page, 0);
+ if (ret)
return ret;
- mph = (struct mode_page_header *) buffer;
+ mph = (struct mode_page_header *)buffer;
offset = be16_to_cpu(mph->desc_length);
size = be16_to_cpu(mph->mode_data_length) + 2;
buffer[offset + 3] = space;
cgc.buflen = size;
- if ((ret = cdrom_mode_select(cdi, &cgc)))
+ ret = cdrom_mode_select(cdi, &cgc);
+ if (ret)
return ret;
pr_info("%s: mrw address space %s selected\n",
@@ -668,6 +583,106 @@ static int cdrom_mrw_set_lba_space(struct cdrom_device_info *cdi, int space)
return 0;
}
+int register_cdrom(struct cdrom_device_info *cdi)
+{
+ static char banner_printed;
+ struct cdrom_device_ops *cdo = cdi->ops;
+ int *change_capability = (int *)&cdo->capability; /* hack */
+
+ cd_dbg(CD_OPEN, "entering register_cdrom\n");
+
+ if (cdo->open == NULL || cdo->release == NULL)
+ return -EINVAL;
+ if (!banner_printed) {
+ pr_info("Uniform CD-ROM driver " REVISION "\n");
+ banner_printed = 1;
+ cdrom_sysctl_register();
+ }
+
+ ENSURE(drive_status, CDC_DRIVE_STATUS);
+ if (cdo->check_events == NULL && cdo->media_changed == NULL)
+ *change_capability = ~(CDC_MEDIA_CHANGED | CDC_SELECT_DISC);
+ ENSURE(tray_move, CDC_CLOSE_TRAY | CDC_OPEN_TRAY);
+ ENSURE(lock_door, CDC_LOCK);
+ ENSURE(select_speed, CDC_SELECT_SPEED);
+ ENSURE(get_last_session, CDC_MULTI_SESSION);
+ ENSURE(get_mcn, CDC_MCN);
+ ENSURE(reset, CDC_RESET);
+ ENSURE(generic_packet, CDC_GENERIC_PACKET);
+ cdi->mc_flags = 0;
+ cdo->n_minors = 0;
+ cdi->options = CDO_USE_FFLAGS;
+
+ if (autoclose == 1 && CDROM_CAN(CDC_CLOSE_TRAY))
+ cdi->options |= (int) CDO_AUTO_CLOSE;
+ if (autoeject == 1 && CDROM_CAN(CDC_OPEN_TRAY))
+ cdi->options |= (int) CDO_AUTO_EJECT;
+ if (lockdoor == 1)
+ cdi->options |= (int) CDO_LOCK;
+ if (check_media_type == 1)
+ cdi->options |= (int) CDO_CHECK_TYPE;
+
+ if (CDROM_CAN(CDC_MRW_W))
+ cdi->exit = cdrom_mrw_exit;
+
+ if (cdi->disk)
+ cdi->cdda_method = CDDA_BPC_FULL;
+ else
+ cdi->cdda_method = CDDA_OLD;
+
+ if (!cdo->generic_packet)
+ cdo->generic_packet = cdrom_dummy_generic_packet;
+
+ cd_dbg(CD_REG_UNREG, "drive \"/dev/%s\" registered\n", cdi->name);
+ mutex_lock(&cdrom_mutex);
+ list_add(&cdi->list, &cdrom_list);
+ mutex_unlock(&cdrom_mutex);
+ return 0;
+}
+#undef ENSURE
+
+void unregister_cdrom(struct cdrom_device_info *cdi)
+{
+ cd_dbg(CD_OPEN, "entering unregister_cdrom\n");
+
+ mutex_lock(&cdrom_mutex);
+ list_del(&cdi->list);
+ mutex_unlock(&cdrom_mutex);
+
+ if (cdi->exit)
+ cdi->exit(cdi);
+
+ cdi->ops->n_minors--;
+ cd_dbg(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name);
+}
+
+int cdrom_get_media_event(struct cdrom_device_info *cdi,
+ struct media_event_desc *med)
+{
+ struct packet_command cgc;
+ unsigned char buffer[8];
+ struct event_header *eh = (struct event_header *)buffer;
+
+ init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+ cgc.cmd[0] = GPCMD_GET_EVENT_STATUS_NOTIFICATION;
+ cgc.cmd[1] = 1; /* IMMED */
+ cgc.cmd[4] = 1 << 4; /* media event */
+ cgc.cmd[8] = sizeof(buffer);
+ cgc.quiet = 1;
+
+ if (cdi->ops->generic_packet(cdi, &cgc))
+ return 1;
+
+ if (be16_to_cpu(eh->data_len) < sizeof(*med))
+ return 1;
+
+ if (eh->nea || eh->notification_class != 0x4)
+ return 1;
+
+ memcpy(med, &buffer[sizeof(*eh)], sizeof(*med));
+ return 0;
+}
+
static int cdrom_get_random_writable(struct cdrom_device_info *cdi,
struct rwrt_feature_desc *rfd)
{
@@ -839,7 +854,7 @@ static int cdrom_ram_open_write(struct cdrom_device_info *cdi)
else if (CDF_RWRT == be16_to_cpu(rfd.feature_code))
ret = !rfd.curr;
- cdinfo(CD_OPEN, "can open for random write\n");
+ cd_dbg(CD_OPEN, "can open for random write\n");
return ret;
}
@@ -928,12 +943,12 @@ static void cdrom_dvd_rw_close_write(struct cdrom_device_info *cdi)
struct packet_command cgc;
if (cdi->mmc3_profile != 0x1a) {
- cdinfo(CD_CLOSE, "%s: No DVD+RW\n", cdi->name);
+ cd_dbg(CD_CLOSE, "%s: No DVD+RW\n", cdi->name);
return;
}
if (!cdi->media_written) {
- cdinfo(CD_CLOSE, "%s: DVD+RW media clean\n", cdi->name);
+ cd_dbg(CD_CLOSE, "%s: DVD+RW media clean\n", cdi->name);
return;
}
@@ -969,82 +984,74 @@ static int cdrom_close_write(struct cdrom_device_info *cdi)
#endif
}
-/* We use the open-option O_NONBLOCK to indicate that the
- * purpose of opening is only for subsequent ioctl() calls; no device
- * integrity checks are performed.
- *
- * We hope that all cd-player programs will adopt this convention. It
- * is in their own interest: device control becomes a lot easier
- * this way.
- */
-int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev, fmode_t mode)
+/* badly broken, I know. Is due for a fixup anytime. */
+static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype *tracks)
{
- int ret;
-
- cdinfo(CD_OPEN, "entering cdrom_open\n");
-
- /* open is event synchronization point, check events first */
- check_disk_change(bdev);
-
- /* if this was a O_NONBLOCK open and we should honor the flags,
- * do a quick open without drive/disc integrity checks. */
- cdi->use_count++;
- if ((mode & FMODE_NDELAY) && (cdi->options & CDO_USE_FFLAGS)) {
- ret = cdi->ops->open(cdi, 1);
- } else {
- ret = open_for_data(cdi);
- if (ret)
- goto err;
- cdrom_mmc3_profile(cdi);
- if (mode & FMODE_WRITE) {
- ret = -EROFS;
- if (cdrom_open_write(cdi))
- goto err_release;
- if (!CDROM_CAN(CDC_RAM))
- goto err_release;
- ret = 0;
- cdi->media_written = 0;
- }
+ struct cdrom_tochdr header;
+ struct cdrom_tocentry entry;
+ int ret, i;
+ tracks->data = 0;
+ tracks->audio = 0;
+ tracks->cdi = 0;
+ tracks->xa = 0;
+ tracks->error = 0;
+ cd_dbg(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n");
+ /* Grab the TOC header so we can see how many tracks there are */
+ ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header);
+ if (ret) {
+ if (ret == -ENOMEDIUM)
+ tracks->error = CDS_NO_DISC;
+ else
+ tracks->error = CDS_NO_INFO;
+ return;
}
-
- if (ret)
- goto err;
-
- cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n",
- cdi->name, cdi->use_count);
- return 0;
-err_release:
- if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
- cdi->ops->lock_door(cdi, 0);
- cdinfo(CD_OPEN, "door unlocked.\n");
+ /* check what type of tracks are on this disc */
+ entry.cdte_format = CDROM_MSF;
+ for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) {
+ entry.cdte_track = i;
+ if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) {
+ tracks->error = CDS_NO_INFO;
+ return;
+ }
+ if (entry.cdte_ctrl & CDROM_DATA_TRACK) {
+ if (entry.cdte_format == 0x10)
+ tracks->cdi++;
+ else if (entry.cdte_format == 0x20)
+ tracks->xa++;
+ else
+ tracks->data++;
+ } else {
+ tracks->audio++;
+ }
+ cd_dbg(CD_COUNT_TRACKS, "track %d: format=%d, ctrl=%d\n",
+ i, entry.cdte_format, entry.cdte_ctrl);
}
- cdi->ops->release(cdi);
-err:
- cdi->use_count--;
- return ret;
+ cd_dbg(CD_COUNT_TRACKS, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n",
+ header.cdth_trk1, tracks->audio, tracks->data,
+ tracks->cdi, tracks->xa);
}
static
-int open_for_data(struct cdrom_device_info * cdi)
+int open_for_data(struct cdrom_device_info *cdi)
{
int ret;
struct cdrom_device_ops *cdo = cdi->ops;
tracktype tracks;
- cdinfo(CD_OPEN, "entering open_for_data\n");
+ cd_dbg(CD_OPEN, "entering open_for_data\n");
/* Check if the driver can report drive status. If it can, we
can do clever things. If it can't, well, we at least tried! */
if (cdo->drive_status != NULL) {
ret = cdo->drive_status(cdi, CDSL_CURRENT);
- cdinfo(CD_OPEN, "drive_status=%d\n", ret);
+ cd_dbg(CD_OPEN, "drive_status=%d\n", ret);
if (ret == CDS_TRAY_OPEN) {
- cdinfo(CD_OPEN, "the tray is open...\n");
+ cd_dbg(CD_OPEN, "the tray is open...\n");
/* can/may i close it? */
if (CDROM_CAN(CDC_CLOSE_TRAY) &&
cdi->options & CDO_AUTO_CLOSE) {
- cdinfo(CD_OPEN, "trying to close the tray.\n");
+ cd_dbg(CD_OPEN, "trying to close the tray\n");
ret=cdo->tray_move(cdi,0);
if (ret) {
- cdinfo(CD_OPEN, "bummer. tried to close the tray but failed.\n");
+ cd_dbg(CD_OPEN, "bummer. tried to close the tray but failed.\n");
/* Ignore the error from the low
level driver. We don't care why it
couldn't close the tray. We only care
@@ -1054,19 +1061,19 @@ int open_for_data(struct cdrom_device_info * cdi)
goto clean_up_and_return;
}
} else {
- cdinfo(CD_OPEN, "bummer. this drive can't close the tray.\n");
+ cd_dbg(CD_OPEN, "bummer. this drive can't close the tray.\n");
ret=-ENOMEDIUM;
goto clean_up_and_return;
}
/* Ok, the door should be closed now.. Check again */
ret = cdo->drive_status(cdi, CDSL_CURRENT);
if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
- cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n");
- cdinfo(CD_OPEN, "tray might not contain a medium.\n");
+ cd_dbg(CD_OPEN, "bummer. the tray is still not closed.\n");
+ cd_dbg(CD_OPEN, "tray might not contain a medium\n");
ret=-ENOMEDIUM;
goto clean_up_and_return;
}
- cdinfo(CD_OPEN, "the tray is now closed.\n");
+ cd_dbg(CD_OPEN, "the tray is now closed\n");
}
/* the door should be closed now, check for the disc */
ret = cdo->drive_status(cdi, CDSL_CURRENT);
@@ -1077,7 +1084,7 @@ int open_for_data(struct cdrom_device_info * cdi)
}
cdrom_count_tracks(cdi, &tracks);
if (tracks.error == CDS_NO_DISC) {
- cdinfo(CD_OPEN, "bummer. no disc.\n");
+ cd_dbg(CD_OPEN, "bummer. no disc.\n");
ret=-ENOMEDIUM;
goto clean_up_and_return;
}
@@ -1087,34 +1094,34 @@ int open_for_data(struct cdrom_device_info * cdi)
if (cdi->options & CDO_CHECK_TYPE) {
/* give people a warning shot, now that CDO_CHECK_TYPE
is the default case! */
- cdinfo(CD_OPEN, "bummer. wrong media type.\n");
- cdinfo(CD_WARNING, "pid %d must open device O_NONBLOCK!\n",
- (unsigned int)task_pid_nr(current));
+ cd_dbg(CD_OPEN, "bummer. wrong media type.\n");
+ cd_dbg(CD_WARNING, "pid %d must open device O_NONBLOCK!\n",
+ (unsigned int)task_pid_nr(current));
ret=-EMEDIUMTYPE;
goto clean_up_and_return;
}
else {
- cdinfo(CD_OPEN, "wrong media type, but CDO_CHECK_TYPE not set.\n");
+ cd_dbg(CD_OPEN, "wrong media type, but CDO_CHECK_TYPE not set\n");
}
}
- cdinfo(CD_OPEN, "all seems well, opening the device.\n");
+ cd_dbg(CD_OPEN, "all seems well, opening the devicen");
/* all seems well, we can open the device */
ret = cdo->open(cdi, 0); /* open for data */
- cdinfo(CD_OPEN, "opening the device gave me %d.\n", ret);
+ cd_dbg(CD_OPEN, "opening the device gave me %d\n", ret);
/* After all this careful checking, we shouldn't have problems
opening the device, but we don't want the device locked if
this somehow fails... */
if (ret) {
- cdinfo(CD_OPEN, "open device failed.\n");
+ cd_dbg(CD_OPEN, "open device failed\n");
goto clean_up_and_return;
}
if (CDROM_CAN(CDC_LOCK) && (cdi->options & CDO_LOCK)) {
cdo->lock_door(cdi, 1);
- cdinfo(CD_OPEN, "door locked.\n");
+ cd_dbg(CD_OPEN, "door locked\n");
}
- cdinfo(CD_OPEN, "device opened successfully.\n");
+ cd_dbg(CD_OPEN, "device opened successfully\n");
return ret;
/* Something failed. Try to unlock the drive, because some drivers
@@ -1123,14 +1130,70 @@ int open_for_data(struct cdrom_device_info * cdi)
This ensures that the drive gets unlocked after a mount fails. This
is a goto to avoid bloating the driver with redundant code. */
clean_up_and_return:
- cdinfo(CD_OPEN, "open failed.\n");
+ cd_dbg(CD_OPEN, "open failed\n");
if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
cdo->lock_door(cdi, 0);
- cdinfo(CD_OPEN, "door unlocked.\n");
+ cd_dbg(CD_OPEN, "door unlocked\n");
}
return ret;
}
+/* We use the open-option O_NONBLOCK to indicate that the
+ * purpose of opening is only for subsequent ioctl() calls; no device
+ * integrity checks are performed.
+ *
+ * We hope that all cd-player programs will adopt this convention. It
+ * is in their own interest: device control becomes a lot easier
+ * this way.
+ */
+int cdrom_open(struct cdrom_device_info *cdi, struct block_device *bdev,
+ fmode_t mode)
+{
+ int ret;
+
+ cd_dbg(CD_OPEN, "entering cdrom_open\n");
+
+ /* open is event synchronization point, check events first */
+ check_disk_change(bdev);
+
+ /* if this was a O_NONBLOCK open and we should honor the flags,
+ * do a quick open without drive/disc integrity checks. */
+ cdi->use_count++;
+ if ((mode & FMODE_NDELAY) && (cdi->options & CDO_USE_FFLAGS)) {
+ ret = cdi->ops->open(cdi, 1);
+ } else {
+ ret = open_for_data(cdi);
+ if (ret)
+ goto err;
+ cdrom_mmc3_profile(cdi);
+ if (mode & FMODE_WRITE) {
+ ret = -EROFS;
+ if (cdrom_open_write(cdi))
+ goto err_release;
+ if (!CDROM_CAN(CDC_RAM))
+ goto err_release;
+ ret = 0;
+ cdi->media_written = 0;
+ }
+ }
+
+ if (ret)
+ goto err;
+
+ cd_dbg(CD_OPEN, "Use count for \"/dev/%s\" now %d\n",
+ cdi->name, cdi->use_count);
+ return 0;
+err_release:
+ if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
+ cdi->ops->lock_door(cdi, 0);
+ cd_dbg(CD_OPEN, "door unlocked\n");
+ }
+ cdi->ops->release(cdi);
+err:
+ cdi->use_count--;
+ return ret;
+}
+
/* This code is similar to that in open_for_data. The routine is called
whenever an audio play operation is requested.
*/
@@ -1139,21 +1202,21 @@ static int check_for_audio_disc(struct cdrom_device_info * cdi,
{
int ret;
tracktype tracks;
- cdinfo(CD_OPEN, "entering check_for_audio_disc\n");
+ cd_dbg(CD_OPEN, "entering check_for_audio_disc\n");
if (!(cdi->options & CDO_CHECK_TYPE))
return 0;
if (cdo->drive_status != NULL) {
ret = cdo->drive_status(cdi, CDSL_CURRENT);
- cdinfo(CD_OPEN, "drive_status=%d\n", ret);
+ cd_dbg(CD_OPEN, "drive_status=%d\n", ret);
if (ret == CDS_TRAY_OPEN) {
- cdinfo(CD_OPEN, "the tray is open...\n");
+ cd_dbg(CD_OPEN, "the tray is open...\n");
/* can/may i close it? */
if (CDROM_CAN(CDC_CLOSE_TRAY) &&
cdi->options & CDO_AUTO_CLOSE) {
- cdinfo(CD_OPEN, "trying to close the tray.\n");
+ cd_dbg(CD_OPEN, "trying to close the tray\n");
ret=cdo->tray_move(cdi,0);
if (ret) {
- cdinfo(CD_OPEN, "bummer. tried to close tray but failed.\n");
+ cd_dbg(CD_OPEN, "bummer. tried to close tray but failed.\n");
/* Ignore the error from the low
level driver. We don't care why it
couldn't close the tray. We only care
@@ -1162,20 +1225,20 @@ static int check_for_audio_disc(struct cdrom_device_info * cdi,
return -ENOMEDIUM;
}
} else {
- cdinfo(CD_OPEN, "bummer. this driver can't close the tray.\n");
+ cd_dbg(CD_OPEN, "bummer. this driver can't close the tray.\n");
return -ENOMEDIUM;
}
/* Ok, the door should be closed now.. Check again */
ret = cdo->drive_status(cdi, CDSL_CURRENT);
if ((ret == CDS_NO_DISC) || (ret==CDS_TRAY_OPEN)) {
- cdinfo(CD_OPEN, "bummer. the tray is still not closed.\n");
+ cd_dbg(CD_OPEN, "bummer. the tray is still not closed.\n");
return -ENOMEDIUM;
}
if (ret!=CDS_DISC_OK) {
- cdinfo(CD_OPEN, "bummer. disc isn't ready.\n");
+ cd_dbg(CD_OPEN, "bummer. disc isn't ready.\n");
return -EIO;
}
- cdinfo(CD_OPEN, "the tray is now closed.\n");
+ cd_dbg(CD_OPEN, "the tray is now closed\n");
}
}
cdrom_count_tracks(cdi, &tracks);
@@ -1193,17 +1256,18 @@ void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode)
struct cdrom_device_ops *cdo = cdi->ops;
int opened_for_data;
- cdinfo(CD_CLOSE, "entering cdrom_release\n");
+ cd_dbg(CD_CLOSE, "entering cdrom_release\n");
if (cdi->use_count > 0)
cdi->use_count--;
if (cdi->use_count == 0) {
- cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name);
+ cd_dbg(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n",
+ cdi->name);
cdrom_dvd_rw_close_write(cdi);
if ((cdo->capability & CDC_LOCK) && !cdi->keeplocked) {
- cdinfo(CD_CLOSE, "Unlocking door!\n");
+ cd_dbg(CD_CLOSE, "Unlocking door!\n");
cdo->lock_door(cdi, 0);
}
}
@@ -1262,7 +1326,7 @@ static int cdrom_slot_status(struct cdrom_device_info *cdi, int slot)
struct cdrom_changer_info *info;
int ret;
- cdinfo(CD_CHANGER, "entering cdrom_slot_status()\n");
+ cd_dbg(CD_CHANGER, "entering cdrom_slot_status()\n");
if (cdi->sanyo_slot)
return CDS_NO_INFO;
@@ -1292,7 +1356,7 @@ int cdrom_number_of_slots(struct cdrom_device_info *cdi)
int nslots = 1;
struct cdrom_changer_info *info;
- cdinfo(CD_CHANGER, "entering cdrom_number_of_slots()\n");
+ cd_dbg(CD_CHANGER, "entering cdrom_number_of_slots()\n");
/* cdrom_read_mech_status requires a valid value for capacity: */
cdi->capacity = 0;
@@ -1313,7 +1377,7 @@ static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot)
{
struct packet_command cgc;
- cdinfo(CD_CHANGER, "entering cdrom_load_unload()\n");
+ cd_dbg(CD_CHANGER, "entering cdrom_load_unload()\n");
if (cdi->sanyo_slot && slot < 0)
return 0;
@@ -1342,7 +1406,7 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
int curslot;
int ret;
- cdinfo(CD_CHANGER, "entering cdrom_select_disc()\n");
+ cd_dbg(CD_CHANGER, "entering cdrom_select_disc()\n");
if (!CDROM_CAN(CDC_SELECT_DISC))
return -EDRIVE_CANT_DO_THIS;
@@ -1476,51 +1540,6 @@ int cdrom_media_changed(struct cdrom_device_info *cdi)
return media_changed(cdi, 0);
}
-/* badly broken, I know. Is due for a fixup anytime. */
-static void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks)
-{
- struct cdrom_tochdr header;
- struct cdrom_tocentry entry;
- int ret, i;
- tracks->data=0;
- tracks->audio=0;
- tracks->cdi=0;
- tracks->xa=0;
- tracks->error=0;
- cdinfo(CD_COUNT_TRACKS, "entering cdrom_count_tracks\n");
- /* Grab the TOC header so we can see how many tracks there are */
- if ((ret = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header))) {
- if (ret == -ENOMEDIUM)
- tracks->error = CDS_NO_DISC;
- else
- tracks->error = CDS_NO_INFO;
- return;
- }
- /* check what type of tracks are on this disc */
- entry.cdte_format = CDROM_MSF;
- for (i = header.cdth_trk0; i <= header.cdth_trk1; i++) {
- entry.cdte_track = i;
- if (cdi->ops->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry)) {
- tracks->error=CDS_NO_INFO;
- return;
- }
- if (entry.cdte_ctrl & CDROM_DATA_TRACK) {
- if (entry.cdte_format == 0x10)
- tracks->cdi++;
- else if (entry.cdte_format == 0x20)
- tracks->xa++;
- else
- tracks->data++;
- } else
- tracks->audio++;
- cdinfo(CD_COUNT_TRACKS, "track %d: format=%d, ctrl=%d\n",
- i, entry.cdte_format, entry.cdte_ctrl);
- }
- cdinfo(CD_COUNT_TRACKS, "disc has %d tracks: %d=audio %d=data %d=Cd-I %d=XA\n",
- header.cdth_trk1, tracks->audio, tracks->data,
- tracks->cdi, tracks->xa);
-}
-
/* Requests to the low-level drivers will /always/ be done in the
following format convention:
@@ -1632,7 +1651,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
switch (ai->type) {
/* LU data send */
case DVD_LU_SEND_AGID:
- cdinfo(CD_DVD, "entering DVD_LU_SEND_AGID\n");
+ cd_dbg(CD_DVD, "entering DVD_LU_SEND_AGID\n");
cgc.quiet = 1;
setup_report_key(&cgc, ai->lsa.agid, 0);
@@ -1644,7 +1663,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
break;
case DVD_LU_SEND_KEY1:
- cdinfo(CD_DVD, "entering DVD_LU_SEND_KEY1\n");
+ cd_dbg(CD_DVD, "entering DVD_LU_SEND_KEY1\n");
setup_report_key(&cgc, ai->lsk.agid, 2);
if ((ret = cdo->generic_packet(cdi, &cgc)))
@@ -1655,7 +1674,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
break;
case DVD_LU_SEND_CHALLENGE:
- cdinfo(CD_DVD, "entering DVD_LU_SEND_CHALLENGE\n");
+ cd_dbg(CD_DVD, "entering DVD_LU_SEND_CHALLENGE\n");
setup_report_key(&cgc, ai->lsc.agid, 1);
if ((ret = cdo->generic_packet(cdi, &cgc)))
@@ -1667,7 +1686,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
/* Post-auth key */
case DVD_LU_SEND_TITLE_KEY:
- cdinfo(CD_DVD, "entering DVD_LU_SEND_TITLE_KEY\n");
+ cd_dbg(CD_DVD, "entering DVD_LU_SEND_TITLE_KEY\n");
cgc.quiet = 1;
setup_report_key(&cgc, ai->lstk.agid, 4);
cgc.cmd[5] = ai->lstk.lba;
@@ -1686,7 +1705,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
break;
case DVD_LU_SEND_ASF:
- cdinfo(CD_DVD, "entering DVD_LU_SEND_ASF\n");
+ cd_dbg(CD_DVD, "entering DVD_LU_SEND_ASF\n");
setup_report_key(&cgc, ai->lsasf.agid, 5);
if ((ret = cdo->generic_packet(cdi, &cgc)))
@@ -1697,7 +1716,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
/* LU data receive (LU changes state) */
case DVD_HOST_SEND_CHALLENGE:
- cdinfo(CD_DVD, "entering DVD_HOST_SEND_CHALLENGE\n");
+ cd_dbg(CD_DVD, "entering DVD_HOST_SEND_CHALLENGE\n");
setup_send_key(&cgc, ai->hsc.agid, 1);
buf[1] = 0xe;
copy_chal(&buf[4], ai->hsc.chal);
@@ -1709,7 +1728,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
break;
case DVD_HOST_SEND_KEY2:
- cdinfo(CD_DVD, "entering DVD_HOST_SEND_KEY2\n");
+ cd_dbg(CD_DVD, "entering DVD_HOST_SEND_KEY2\n");
setup_send_key(&cgc, ai->hsk.agid, 3);
buf[1] = 0xa;
copy_key(&buf[4], ai->hsk.key);
@@ -1724,7 +1743,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
/* Misc */
case DVD_INVALIDATE_AGID:
cgc.quiet = 1;
- cdinfo(CD_DVD, "entering DVD_INVALIDATE_AGID\n");
+ cd_dbg(CD_DVD, "entering DVD_INVALIDATE_AGID\n");
setup_report_key(&cgc, ai->lsa.agid, 0x3f);
if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret;
@@ -1732,7 +1751,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
/* Get region settings */
case DVD_LU_SEND_RPC_STATE:
- cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
+ cd_dbg(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
setup_report_key(&cgc, 0, 8);
memset(&rpc_state, 0, sizeof(rpc_state_t));
cgc.buffer = (char *) &rpc_state;
@@ -1749,7 +1768,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
/* Set region settings */
case DVD_HOST_SEND_RPC_STATE:
- cdinfo(CD_DVD, "entering DVD_HOST_SEND_RPC_STATE\n");
+ cd_dbg(CD_DVD, "entering DVD_HOST_SEND_RPC_STATE\n");
setup_send_key(&cgc, 0, 6);
buf[1] = 6;
buf[4] = ai->hrpcs.pdrc;
@@ -1759,7 +1778,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
break;
default:
- cdinfo(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type);
+ cd_dbg(CD_WARNING, "Invalid DVD key ioctl (%d)\n", ai->type);
return -ENOTTY;
}
@@ -1891,7 +1910,8 @@ static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s,
s->bca.len = buf[0] << 8 | buf[1];
if (s->bca.len < 12 || s->bca.len > 188) {
- cdinfo(CD_WARNING, "Received invalid BCA length (%d)\n", s->bca.len);
+ cd_dbg(CD_WARNING, "Received invalid BCA length (%d)\n",
+ s->bca.len);
ret = -EIO;
goto out;
}
@@ -1927,14 +1947,13 @@ static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s,
s->manufact.len = buf[0] << 8 | buf[1];
if (s->manufact.len < 0) {
- cdinfo(CD_WARNING, "Received invalid manufacture info length"
- " (%d)\n", s->manufact.len);
+ cd_dbg(CD_WARNING, "Received invalid manufacture info length (%d)\n",
+ s->manufact.len);
ret = -EIO;
} else {
if (s->manufact.len > 2048) {
- cdinfo(CD_WARNING, "Received invalid manufacture info "
- "length (%d): truncating to 2048\n",
- s->manufact.len);
+ cd_dbg(CD_WARNING, "Received invalid manufacture info length (%d): truncating to 2048\n",
+ s->manufact.len);
s->manufact.len = 2048;
}
memcpy(s->manufact.value, &buf[4], s->manufact.len);
@@ -1965,8 +1984,8 @@ static int dvd_read_struct(struct cdrom_device_info *cdi, dvd_struct *s,
return dvd_read_manufact(cdi, s, cgc);
default:
- cdinfo(CD_WARNING, ": Invalid DVD structure read requested (%d)\n",
- s->type);
+ cd_dbg(CD_WARNING, ": Invalid DVD structure read requested (%d)\n",
+ s->type);
return -EINVAL;
}
}
@@ -2255,7 +2274,7 @@ static int cdrom_ioctl_multisession(struct cdrom_device_info *cdi,
u8 requested_format;
int ret;
- cdinfo(CD_DO_IOCTL, "entering CDROMMULTISESSION\n");
+ cd_dbg(CD_DO_IOCTL, "entering CDROMMULTISESSION\n");
if (!(cdi->ops->capability & CDC_MULTI_SESSION))
return -ENOSYS;
@@ -2277,13 +2296,13 @@ static int cdrom_ioctl_multisession(struct cdrom_device_info *cdi,
if (copy_to_user(argp, &ms_info, sizeof(ms_info)))
return -EFAULT;
- cdinfo(CD_DO_IOCTL, "CDROMMULTISESSION successful\n");
+ cd_dbg(CD_DO_IOCTL, "CDROMMULTISESSION successful\n");
return 0;
}
static int cdrom_ioctl_eject(struct cdrom_device_info *cdi)
{
- cdinfo(CD_DO_IOCTL, "entering CDROMEJECT\n");
+ cd_dbg(CD_DO_IOCTL, "entering CDROMEJECT\n");
if (!CDROM_CAN(CDC_OPEN_TRAY))
return -ENOSYS;
@@ -2300,7 +2319,7 @@ static int cdrom_ioctl_eject(struct cdrom_device_info *cdi)
static int cdrom_ioctl_closetray(struct cdrom_device_info *cdi)
{
- cdinfo(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n");
+ cd_dbg(CD_DO_IOCTL, "entering CDROMCLOSETRAY\n");
if (!CDROM_CAN(CDC_CLOSE_TRAY))
return -ENOSYS;
@@ -2310,7 +2329,7 @@ static int cdrom_ioctl_closetray(struct cdrom_device_info *cdi)
static int cdrom_ioctl_eject_sw(struct cdrom_device_info *cdi,
unsigned long arg)
{
- cdinfo(CD_DO_IOCTL, "entering CDROMEJECT_SW\n");
+ cd_dbg(CD_DO_IOCTL, "entering CDROMEJECT_SW\n");
if (!CDROM_CAN(CDC_OPEN_TRAY))
return -ENOSYS;
@@ -2329,7 +2348,7 @@ static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi,
struct cdrom_changer_info *info;
int ret;
- cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n");
+ cd_dbg(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n");
if (!CDROM_CAN(CDC_MEDIA_CHANGED))
return -ENOSYS;
@@ -2355,7 +2374,7 @@ static int cdrom_ioctl_media_changed(struct cdrom_device_info *cdi,
static int cdrom_ioctl_set_options(struct cdrom_device_info *cdi,
unsigned long arg)
{
- cdinfo(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n");
+ cd_dbg(CD_DO_IOCTL, "entering CDROM_SET_OPTIONS\n");
/*
* Options need to be in sync with capability.
@@ -2383,7 +2402,7 @@ static int cdrom_ioctl_set_options(struct cdrom_device_info *cdi,
static int cdrom_ioctl_clear_options(struct cdrom_device_info *cdi,
unsigned long arg)