summaryrefslogtreecommitdiffstats
path: root/drivers/cdrom
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cdrom')
-rw-r--r--drivers/cdrom/cdrom.c81
1 files changed, 57 insertions, 24 deletions
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index c20ce1b93..c66efc8c7 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -187,14 +187,23 @@
-- Fixed CDDA ripping with cdda2wav - accept much larger requests of
number of frames and split the reads in blocks of 8.
- 3.05 Dec 13, 1999 - Jens Axboe <axboe@image.dk>
+ 3.06 Dec 13, 1999 - Jens Axboe <axboe@image.dk>
-- Added support for changing the region of DVD drives.
-- Added sense data to generic command.
+
+ 3.07 Feb 2, 2000 - Jens Axboe <axboe@suse.de>
+ -- Do same "read header length" trick in cdrom_get_disc_info() as
+ we do in cdrom_get_track_info() -- some drive don't obbey specs and
+ fail if they can't supply the full Mt Fuji size table.
+ -- Deleted stuff related to setting up write modes. It has a different
+ home now.
+ -- Clear header length in mode_select unconditionally.
+ -- Removed the register_disk() that was added, not needed here.
-------------------------------------------------------------------------*/
-#define REVISION "Revision: 3.06"
-#define VERSION "Id: cdrom.c 3.06 1999/12/13"
+#define REVISION "Revision: 3.07"
+#define VERSION "Id: cdrom.c 3.07 2000/02/02"
/* I use an error-log mask to give fine grain control over the type of
messages dumped to the system logs. The available masks include: */
@@ -415,7 +424,6 @@ int unregister_cdrom(struct cdrom_device_info *unreg)
return 0;
}
-static
struct cdrom_device_info *cdrom_find_device(kdev_t dev)
{
struct cdrom_device_info *cdi;
@@ -682,7 +690,7 @@ static int cdrom_read_mech_status(struct cdrom_device_info *cdi,
length = sizeof(struct cdrom_mechstat_header) +
cdi->capacity * sizeof(struct cdrom_slot);
- init_cdrom_command(&cgc, buf, length);
+ init_cdrom_command(&cgc, buf, length, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_MECHANISM_STATUS;
cgc.cmd[8] = (length >> 8) & 0xff;
cgc.cmd[9] = length & 0xff;
@@ -737,7 +745,7 @@ static int cdrom_load_unload(struct cdrom_device_info *cdi, int slot)
if (cdi->sanyo_slot && slot < 0)
return 0;
- init_cdrom_command(&cgc, NULL, 0);
+ init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
cgc.cmd[0] = GPCMD_LOAD_UNLOAD;
cgc.cmd[4] = 2 + (slot >= 0);
cgc.cmd[8] = slot;
@@ -921,12 +929,15 @@ void sanitize_format(union cdrom_addr *addr,
*curr = requested;
}
-void init_cdrom_command(struct cdrom_generic_command *cgc, void *buf, int len)
+void init_cdrom_command(struct cdrom_generic_command *cgc, void *buf, int len,
+ int type)
{
memset(cgc, 0, sizeof(struct cdrom_generic_command));
- memset(buf, 0, len);
+ if (buf)
+ memset(buf, 0, len);
cgc->buffer = (char *) buf;
cgc->buflen = len;
+ cgc->data_direction = type;
}
/* DVD handling */
@@ -953,6 +964,7 @@ static void setup_report_key(struct cdrom_generic_command *cgc, unsigned agid, u
}
}
cgc->cmd[9] = cgc->buflen;
+ cgc->data_direction = CGC_DATA_WRITE;
}
static void setup_send_key(struct cdrom_generic_command *cgc, unsigned agid, unsigned type)
@@ -974,6 +986,7 @@ static void setup_send_key(struct cdrom_generic_command *cgc, unsigned agid, uns
}
}
cgc->cmd[9] = cgc->buflen;
+ cgc->data_direction = CGC_DATA_READ;
}
static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
@@ -983,7 +996,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
struct cdrom_generic_command cgc;
struct cdrom_device_ops *cdo = cdi->ops;
- init_cdrom_command(&cgc, buf, 0);
+ init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);
switch (ai->type) {
/* LU data send */
@@ -1124,7 +1137,7 @@ static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s)
struct cdrom_generic_command cgc;
struct cdrom_device_ops *cdo = cdi->ops;
- init_cdrom_command(&cgc, buf, sizeof(buf));
+ init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[6] = s->physical.layer_num;
cgc.cmd[7] = s->type;
@@ -1165,7 +1178,7 @@ static int dvd_read_copyright(struct cdrom_device_info *cdi, dvd_struct *s)
struct cdrom_generic_command cgc;
struct cdrom_device_ops *cdo = cdi->ops;
- init_cdrom_command(&cgc, buf, sizeof(buf));
+ init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[6] = s->copyright.layer_num;
cgc.cmd[7] = s->type;
@@ -1193,7 +1206,7 @@ static int dvd_read_disckey(struct cdrom_device_info *cdi, dvd_struct *s)
if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
return -ENOMEM;
- init_cdrom_command(&cgc, buf, size);
+ init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[7] = s->type;
cgc.cmd[8] = size >> 8;
@@ -1214,7 +1227,7 @@ static int dvd_read_bca(struct cdrom_device_info *cdi, dvd_struct *s)
struct cdrom_generic_command cgc;
struct cdrom_device_ops *cdo = cdi->ops;
- init_cdrom_command(&cgc, buf, sizeof(buf));
+ init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[7] = s->type;
cgc.cmd[9] = cgc.buflen = 0xff;
@@ -1244,7 +1257,7 @@ static int dvd_read_manufact(struct cdrom_device_info *cdi, dvd_struct *s)
if ((buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL)
return -ENOMEM;
- init_cdrom_command(&cgc, buf, size);
+ init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[7] = s->type;
cgc.cmd[8] = size >> 8;
@@ -1305,6 +1318,7 @@ int cdrom_mode_sense(struct cdrom_device_info *cdi,
cgc->cmd[2] = page_code | (page_control << 6);
cgc->cmd[7] = cgc->buflen >> 8;
cgc->cmd[8] = cgc->buflen & 0xff;
+ cgc->data_direction = CGC_DATA_READ;
return cdo->generic_packet(cdi, cgc);
}
@@ -1314,11 +1328,12 @@ int cdrom_mode_select(struct cdrom_device_info *cdi,
struct cdrom_device_ops *cdo = cdi->ops;
memset(cgc->cmd, 0, sizeof(cgc->cmd));
-
+ memset(cgc->buffer, 0, 2);
cgc->cmd[0] = GPCMD_MODE_SELECT_10;
cgc->cmd[1] = 0x10; /* PF */
cgc->cmd[7] = cgc->buflen >> 8;
cgc->cmd[8] = cgc->buflen & 0xff;
+ cgc->data_direction = CGC_DATA_WRITE;
return cdo->generic_packet(cdi, cgc);
}
@@ -1330,7 +1345,7 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
char buffer[32];
int ret;
- init_cdrom_command(&cgc, buffer, 16);
+ init_cdrom_command(&cgc, buffer, 16, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_SUBCHANNEL;
cgc.cmd[1] = 2; /* MSF addressing */
cgc.cmd[2] = 0x40; /* request subQ data */
@@ -1812,6 +1827,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
cgc.buffer = (char *) kmalloc(blocksize, GFP_KERNEL);
if (cgc.buffer == NULL)
return -ENOMEM;
+ cgc.data_direction = CGC_DATA_READ;
ret = cdrom_read_block(cdi, &cgc, lba, 1, format, blocksize);
if (!ret)
if (copy_to_user((char *)arg, cgc.buffer, blocksize))
@@ -1849,7 +1865,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
kfree(cgc.buffer);
return -EFAULT;
}
-
+ cgc.data_direction = CGC_DATA_READ;
while (ra.nframes > 0) {
ret = cdrom_read_block(cdi, &cgc, lba, frames, 1,
CD_FRAMESIZE_RAW);
@@ -1913,6 +1929,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
cgc.cmd[7] = entry.cdte_addr.msf.second;
cgc.cmd[8] = entry.cdte_addr.msf.frame;
cgc.cmd[0] = GPCMD_PLAY_AUDIO_MSF;
+ cgc.data_direction = CGC_DATA_NONE;
return cdo->generic_packet(cdi, &cgc);
}
case CDROMPLAYMSF: {
@@ -1926,6 +1943,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
cgc.cmd[6] = msf.cdmsf_min1;
cgc.cmd[7] = msf.cdmsf_sec1;
cgc.cmd[8] = msf.cdmsf_frame1;
+ cgc.data_direction = CGC_DATA_NONE;
return cdo->generic_packet(cdi, &cgc);
}
case CDROMPLAYBLK: {
@@ -1939,6 +1957,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
cgc.cmd[5] = blk.from & 0xff;
cgc.cmd[7] = (blk.len >> 8) & 0xff;
cgc.cmd[8] = blk.len & 0xff;
+ cgc.data_direction = CGC_DATA_NONE;
return cdo->generic_packet(cdi, &cgc);
}
case CDROMVOLCTRL:
@@ -1989,9 +2008,6 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
buffer[offset+13] = volctrl.channel2 & mask[offset+13];
buffer[offset+15] = volctrl.channel3 & mask[offset+15];
- /* clear the first three */
- memset(buffer, 0, 3);
-
/* set volume */
cgc.buffer = buffer;
return cdrom_mode_select(cdi, &cgc);
@@ -2003,6 +2019,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
cgc.cmd[0] = GPCMD_START_STOP_UNIT;
cgc.cmd[1] = 1;
cgc.cmd[4] = (cmd == CDROMSTART) ? 1 : 0;
+ cgc.data_direction = CGC_DATA_NONE;
return cdo->generic_packet(cdi, &cgc);
}
@@ -2011,6 +2028,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
cdinfo(CD_DO_IOCTL, "entering CDROMPAUSE/CDROMRESUME\n");
cgc.cmd[0] = GPCMD_PAUSE_RESUME;
cgc.cmd[8] = (cmd == CDROMRESUME) ? 1 : 0;
+ cgc.data_direction = CGC_DATA_NONE;
return cdo->generic_packet(cdi, &cgc);
}
@@ -2090,7 +2108,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
if (copy && !ret)
__copy_to_user(userbuf, cgc.buffer, cgc.buflen);
/* copy back sense data */
- if (ret && sense != NULL)
+ if (sense != NULL)
if (copy_to_user(sense, cgc.sense, sizeof(struct request_sense)))
ret = -EFAULT;
kfree(cgc.buffer);
@@ -2125,7 +2143,7 @@ int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type,
struct cdrom_generic_command cgc;
int ret;
- init_cdrom_command(&cgc, ti, 8);
+ init_cdrom_command(&cgc, ti, 8, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_TRACK_RZONE_INFO;
cgc.cmd[1] = type & 3;
cgc.cmd[4] = (track & 0xff00) >> 8;
@@ -2145,12 +2163,26 @@ int cdrom_get_disc_info(kdev_t dev, disc_information *di)
struct cdrom_device_info *cdi = cdrom_find_device(dev);
struct cdrom_device_ops *cdo = cdi->ops;
struct cdrom_generic_command cgc;
+ int ret;
/* set up command and get the disc info */
- init_cdrom_command(&cgc, di, sizeof(*di));
+ init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DISC_INFO;
- cgc.cmd[8] = cgc.buflen;
+ cgc.cmd[8] = cgc.buflen = 2;
+ if ((ret = cdo->generic_packet(cdi, &cgc)))
+ return ret;
+
+ /* not all drives have the same disc_info length, so requeue
+ * packet with the length the drive tells us it can supply
+ */
+ cgc.buflen = be16_to_cpu(di->disc_information_length) +
+ sizeof(di->disc_information_length);
+
+ if (cgc.buflen > sizeof(disc_information))
+ cgc.buflen = sizeof(disc_information);
+
+ cgc.cmd[8] = cgc.buflen;
return cdo->generic_packet(cdi, &cgc);
}
@@ -2265,6 +2297,7 @@ EXPORT_SYMBOL(cdrom_select_disc);
EXPORT_SYMBOL(cdrom_mode_select);
EXPORT_SYMBOL(cdrom_mode_sense);
EXPORT_SYMBOL(init_cdrom_command);
+EXPORT_SYMBOL(cdrom_find_device);
#ifdef CONFIG_SYSCTL