summaryrefslogtreecommitdiffstats
path: root/drivers/cdrom
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-19 22:45:37 +0000
commit6d403070f28cd44860fdb3a53be5da0275c65cf4 (patch)
tree0d0e7fe7b5fb7568d19e11d7d862b77a866ce081 /drivers/cdrom
parentecf1bf5f6c2e668d03b0a9fb026db7aa41e292e1 (diff)
Merge with 2.4.0-test1-ac21 + pile of MIPS cleanups to make merging
possible. Chainsawed RM200 kernel to compile again. Jazz machine status unknown.
Diffstat (limited to 'drivers/cdrom')
-rw-r--r--drivers/cdrom/aztcd.c13
-rw-r--r--drivers/cdrom/cdrom.c159
-rw-r--r--drivers/cdrom/cm206.c7
-rw-r--r--drivers/cdrom/mcd.c18
-rw-r--r--drivers/cdrom/optcd.c13
-rw-r--r--drivers/cdrom/sjcd.c21
6 files changed, 164 insertions, 67 deletions
diff --git a/drivers/cdrom/aztcd.c b/drivers/cdrom/aztcd.c
index 767a52dcb..aaad8e0c6 100644
--- a/drivers/cdrom/aztcd.c
+++ b/drivers/cdrom/aztcd.c
@@ -1543,14 +1543,17 @@ int aztcd_open(struct inode *ip, struct file *fp)
#ifdef AZT_DEBUG
printk("aztcd: starting aztcd_open\n");
#endif
+
if (aztPresent == 0)
return -ENXIO; /* no hardware */
+ MOD_INC_USE_COUNT;
+
if (!azt_open_count && azt_state == AZT_S_IDLE)
{ azt_invalidate_buffers();
st = getAztStatus(); /* check drive status */
- if (st == -1) return -EIO; /* drive doesn't respond */
+ if (st == -1) goto err_out; /* drive doesn't respond */
if (st & AST_DOOR_OPEN)
{ /* close door, then get the status again. */
@@ -1563,18 +1566,20 @@ int aztcd_open(struct inode *ip, struct file *fp)
{ printk("aztcd: Disk Changed or No Disk in Drive?\n");
aztTocUpToDate=0;
}
- if (aztUpdateToc()) return -EIO;
+ if (aztUpdateToc()) goto err_out;
}
++azt_open_count;
- MOD_INC_USE_COUNT;
aztLockDoor();
-
#ifdef AZT_DEBUG
printk("aztcd: exiting aztcd_open\n");
#endif
return 0;
+
+err_out:
+ MOD_DEC_USE_COUNT;
+ return -EIO;
}
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index ceb94b7e5..6b117a6be 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -193,7 +193,7 @@
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
+ we do in cdrom_get_track_info() -- some drive don't obey 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.
@@ -211,10 +211,24 @@
dvd_do_auth passed uninitialized data to drive because init_cdrom_command
did not clear a 0 sized buffer.
+ 3.09 May 12, 2000 - Jens Axboe <axboe@suse.de>
+ -- Fix Video-CD on SCSI drives that don't support READ_CD command. In
+ that case switch block size and issue plain READ_10 again, then switch
+ back.
+
+ 3.10 Jun 10, 2000 - Jens Axboe <axboe@suse.de>
+ -- Fix volume control on CD's - old SCSI-II drives now use their own
+ code, as doing MODE6 stuff in here is really not my intention.
+ -- Use READ_DISC_INFO for more reliable end-of-disc.
+
+ 3.11 Jun 12, 2000 - Jens Axboe <axboe@suse.de>
+ -- Fix bug in getting rpc phase 2 region info.
+ -- Reinstate "correct" CDROMPLAYTRKIND
+
-------------------------------------------------------------------------*/
-#define REVISION "Revision: 3.08"
-#define VERSION "Id: cdrom.c 3.08 2000/05/01"
+#define REVISION "Revision: 3.11"
+#define VERSION "Id: cdrom.c 3.11 2000/06/12"
/* 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: */
@@ -285,7 +299,7 @@ MODULE_PARM(check_media_type, "i");
/* 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)
+#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
@@ -465,7 +479,7 @@ int cdrom_open(struct inode *ip, struct file *fp)
if ((cdi = cdrom_find_device(dev)) == NULL)
return -ENODEV;
- if (fp->f_mode & FMODE_WRITE)
+ if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_DVD_RAM))
return -EROFS;
/* if this was a O_NONBLOCK open and we should honor the flags,
@@ -993,6 +1007,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
u_char buf[20];
struct cdrom_generic_command cgc;
struct cdrom_device_ops *cdo = cdi->ops;
+ rpc_state_t rpc_state;
memset(buf, 0, sizeof(buf));
init_cdrom_command(&cgc, buf, 0, CGC_DATA_READ);
@@ -1099,18 +1114,19 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
case DVD_LU_SEND_RPC_STATE:
cdinfo(CD_DVD, "entering DVD_LU_SEND_RPC_STATE\n");
setup_report_key(&cgc, 0, 8);
+ memset(&rpc_state, 0, sizeof(rpc_state_t));
if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret;
- ai->lrpcs.type = (buf[4] >> 6) & 3;
- ai->lrpcs.vra = (buf[4] >> 3) & 7;
- ai->lrpcs.ucca = buf[4] & 7;
- ai->lrpcs.region_mask = buf[5];
- ai->lrpcs.rpc_scheme = buf[6];
+ ai->lrpcs.type = rpc_state.type_code;
+ ai->lrpcs.vra = rpc_state.vra;
+ ai->lrpcs.ucca = rpc_state.ucca;
+ ai->lrpcs.region_mask = rpc_state.region_mask;
+ ai->lrpcs.rpc_scheme = rpc_state.rpc_scheme;
break;
- /* Set region settings */
+ /* Set region settings */
case DVD_HOST_SEND_RPC_STATE:
cdinfo(CD_DVD, "entering DVD_HOST_SEND_RPC_STATE\n");
setup_send_key(&cgc, 0, 6);
@@ -1371,6 +1387,28 @@ static int cdrom_read_subchannel(struct cdrom_device_info *cdi,
return 0;
}
+/*
+ * Specific READ_10 interface
+ */
+static int cdrom_read_cd(struct cdrom_device_info *cdi,
+ struct cdrom_generic_command *cgc, int lba,
+ int blocksize, int nblocks)
+{
+ struct cdrom_device_ops *cdo = cdi->ops;
+
+ memset(&cgc->cmd, 0, sizeof(cgc->cmd));
+ cgc->cmd[0] = GPCMD_READ_10;
+ cgc->cmd[2] = (lba >> 24) & 0xff;
+ cgc->cmd[3] = (lba >> 16) & 0xff;
+ cgc->cmd[4] = (lba >> 8) & 0xff;
+ cgc->cmd[5] = lba & 0xff;
+ cgc->cmd[6] = (nblocks >> 16) & 0xff;
+ cgc->cmd[7] = (nblocks >> 8) & 0xff;
+ cgc->cmd[8] = nblocks & 0xff;
+ cgc->buflen = blocksize * nblocks;
+ return cdo->generic_packet(cdi, cgc);
+}
+
/* very generic interface for reading the various types of blocks */
static int cdrom_read_block(struct cdrom_device_info *cdi,
struct cdrom_generic_command *cgc,
@@ -1787,6 +1825,43 @@ int msf_to_lba(char m, char s, char f)
return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
}
+/*
+ * Required when we need to use READ_10 to issue other than 2048 block
+ * reads
+ */
+static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size)
+{
+ struct cdrom_device_ops *cdo = cdi->ops;
+ struct cdrom_generic_command cgc;
+ struct modesel_head mh;
+ int ret;
+
+ memset(&mh, 0, sizeof(mh));
+ mh.block_desc_length = 0x08;
+ mh.block_length_med = (size >> 8) & 0xff;
+ mh.block_length_lo = size & 0xff;
+
+ memset(&cgc, 0, sizeof(cgc));
+ cgc.cmd[0] = 0x15;
+ cgc.cmd[1] = 1 << 4;
+ cgc.cmd[4] = 12;
+ cgc.buflen = sizeof(mh);
+ cgc.buffer = (char *) &mh;
+ cgc.data_direction = CGC_DATA_WRITE;
+ mh.block_desc_length = 0x08;
+ mh.block_length_med = (size >> 8) & 0xff;
+ mh.block_length_lo = size & 0xff;
+
+ ret = cdo->generic_packet(cdi, &cgc);
+ if (ret) {
+ printk("switch_blocksize failed, ret %x ", ret);
+ if (cgc.sense)
+ printk("sense %02x.%02x.%02x", cgc.sense->sense_key, cgc.sense->asc, cgc.sense->ascq);
+ printk("\n");
+ }
+ return ret;
+}
+
static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
unsigned long arg)
{
@@ -1829,8 +1904,27 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
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))
+ if (ret) {
+ /*
+ * SCSI-II devices are not required to support
+ * READ_CD, so let's try switching block size
+ */
+ /* FIXME: switch back again... */
+ if ((ret = cdrom_switch_blocksize(cdi, blocksize))) {
+ kfree(cgc.buffer);
+ return ret;
+ }
+ cgc.sense = NULL;
+ ret = cdrom_read_cd(cdi, &cgc, lba, blocksize, 1);
+ if (ret) {
+ printk("read_cd failed, ret %x ", ret);
+ if (cgc.sense)
+ printk("sense %02x.%02x.%02x", cgc.sense->sense_key, cgc.sense->asc, cgc.sense->ascq);
+ printk("\n");
+ }
+ ret |= cdrom_switch_blocksize(cdi, blocksize);
+ }
+ if (!ret && copy_to_user((char *)arg, cgc.buffer, blocksize))
ret = -EFAULT;
kfree(cgc.buffer);
return ret;
@@ -1867,8 +1961,7 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
}
cgc.data_direction = CGC_DATA_READ;
while (ra.nframes > 0) {
- ret = cdrom_read_block(cdi, &cgc, lba, frames, 1,
- CD_FRAMESIZE_RAW);
+ ret = cdrom_read_block(cdi, &cgc, lba, frames, 1, CD_FRAMESIZE_RAW);
if (ret) break;
__copy_to_user(ra.buf, cgc.buffer,
CD_FRAMESIZE_RAW * frames);
@@ -1899,37 +1992,15 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
}
case CDROMPLAYTRKIND: {
struct cdrom_ti ti;
- struct cdrom_tocentry entry;
- struct cdrom_tochdr tochdr;
cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
IOCTL_IN(arg, struct cdrom_ti, ti);
- entry.cdte_format = CDROM_MSF;
- /* get toc entry for start and end track */
- if (cdo->audio_ioctl(cdi, CDROMREADTOCHDR, &tochdr))
- return -EINVAL;
- if ((entry.cdte_track = ti.cdti_trk0) > tochdr.cdth_trk1)
- return -EINVAL;
- if (cdo->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry))
- return -EINVAL;
-
- cgc.cmd[3] = entry.cdte_addr.msf.minute;
- cgc.cmd[4] = entry.cdte_addr.msf.second;
- cgc.cmd[5] = entry.cdte_addr.msf.frame;
-
- entry.cdte_track = ti.cdti_trk1 + 1;
- if (entry.cdte_track > tochdr.cdth_trk1)
- entry.cdte_track = CDROM_LEADOUT;
-
- if (cdo->audio_ioctl(cdi, CDROMREADTOCENTRY, &entry))
- return -EINVAL;
-
- cgc.cmd[6] = entry.cdte_addr.msf.minute;
- 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;
+ cgc.cmd[0] = GPCMD_PLAY_AUDIO_TI;
+ cgc.cmd[4] = ti.cdti_trk0;
+ cgc.cmd[5] = ti.cdti_ind0;
+ cgc.cmd[7] = ti.cdti_trk1;
+ cgc.cmd[8] = ti.cdti_ind1;
return cdo->generic_packet(cdi, &cgc);
}
case CDROMPLAYMSF: {
@@ -2158,6 +2229,7 @@ int cdrom_get_track_info(kdev_t dev, __u16 track, __u8 type,
return cdo->generic_packet(cdi, &cgc);
}
+/* requires CD R/RW */
int cdrom_get_disc_info(kdev_t dev, disc_information *di)
{
struct cdrom_device_info *cdi = cdrom_find_device(dev);
@@ -2201,6 +2273,9 @@ int cdrom_get_last_written(kdev_t dev, long *last_written)
if (!CDROM_CAN(CDC_GENERIC_PACKET))
goto use_toc;
+ if (!CDROM_CAN(CDC_CD_R | CDC_CD_RW | CDC_DVD_R | CDC_DVD_RAM))
+ goto use_toc;
+
if ((ret = cdrom_get_disc_info(dev, &di)))
goto use_toc;
diff --git a/drivers/cdrom/cm206.c b/drivers/cdrom/cm206.c
index 45af24484..9e8889ac6 100644
--- a/drivers/cdrom/cm206.c
+++ b/drivers/cdrom/cm206.c
@@ -736,13 +736,14 @@ void get_disc_status(void)
static int cm206_open(struct cdrom_device_info * cdi, int purpose)
{
+ MOD_INC_USE_COUNT;
if (!cd->openfiles) { /* reset only first time */
cd->background=0;
reset_cm260();
cd->adapter_last = -1; /* invalidate adapter memory */
cd->sector_last = -1;
}
- ++cd->openfiles; MOD_INC_USE_COUNT;
+ ++cd->openfiles;
stats(open);
return 0;
}
@@ -757,7 +758,8 @@ static void cm206_release(struct cdrom_device_info * cdi)
cd->sector_last = -1; /* Make our internal buffer invalid */
FIRST_TRACK = 0; /* No valid disc status */
}
- --cd->openfiles; MOD_DEC_USE_COUNT;
+ --cd->openfiles;
+ MOD_DEC_USE_COUNT;
}
/* Empty buffer empties $sectors$ sectors of the adapter card buffer,
@@ -1258,6 +1260,7 @@ static struct cdrom_device_info cm206_info = {
&cm206_dops, /* device operations */
NULL, /* link */
NULL, /* handle (not used by cm206) */
+ 0, /* devfs handle */
0, /* dev */
0, /* mask */
2, /* maximum speed */
diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
index 44cde3738..91bde1a1d 100644
--- a/drivers/cdrom/mcd.c
+++ b/drivers/cdrom/mcd.c
@@ -1110,12 +1110,16 @@ static int mcd_open(struct cdrom_device_info * cdi, int purpose)
if (mcdPresent == 0)
return -ENXIO; /* no hardware */
- if (!mcd_open_count && mcd_state == MCD_S_IDLE) {
+ MOD_INC_USE_COUNT;
+
+ if (mcd_open_count || mcd_state != MCD_S_IDLE)
+ goto bump_count;
+
mcd_invalidate_buffers();
do {
st = statusCmd(); /* check drive status */
if (st == -1)
- return -EIO; /* drive doesn't respond */
+ goto err_out; /* drive doesn't respond */
if ((st & MST_READY) == 0) { /* no disk? wait a sec... */
current->state = TASK_INTERRUPTIBLE;
schedule_timeout(HZ);
@@ -1123,11 +1127,15 @@ static int mcd_open(struct cdrom_device_info * cdi, int purpose)
} while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);
if (updateToc() < 0)
- return -EIO;
- }
+ goto err_out;
+
+bump_count:
++mcd_open_count;
- MOD_INC_USE_COUNT;
return 0;
+
+err_out:
+ MOD_DEC_USE_COUNT;
+ return -EIO;
}
diff --git a/drivers/cdrom/optcd.c b/drivers/cdrom/optcd.c
index ad190c6ef..07f1f030c 100644
--- a/drivers/cdrom/optcd.c
+++ b/drivers/cdrom/optcd.c
@@ -1871,6 +1871,8 @@ static int opt_open(struct inode *ip, struct file *fp)
{
DEBUG((DEBUG_VFS, "starting opt_open"));
+ MOD_INC_USE_COUNT;
+
if (!open_count && state == S_IDLE) {
int status;
@@ -1885,12 +1887,12 @@ static int opt_open(struct inode *ip, struct file *fp)
status = drive_status();
if (status < 0) {
DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
- return -EIO;
+ goto err_out;
}
DEBUG((DEBUG_VFS, "status: %02x", status));
if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
printk(KERN_INFO "optcd: no disk or door open\n");
- return -EIO;
+ goto err_out;
}
status = exec_cmd(COMLOCK); /* Lock door */
if (status < 0) {
@@ -1904,15 +1906,18 @@ static int opt_open(struct inode *ip, struct file *fp)
DEBUG((DEBUG_VFS,
"exec_cmd COMUNLOCK: %02x", -status));
}
- return -EIO;
+ goto err_out;
}
open_count++;
}
- MOD_INC_USE_COUNT;
DEBUG((DEBUG_VFS, "exiting opt_open"));
return 0;
+
+err_out:
+ MOD_DEC_USE_COUNT;
+ return -EIO;
}
diff --git a/drivers/cdrom/sjcd.c b/drivers/cdrom/sjcd.c
index 5b8db1278..82dd5e5b9 100644
--- a/drivers/cdrom/sjcd.c
+++ b/drivers/cdrom/sjcd.c
@@ -58,10 +58,7 @@
#define SJCD_VERSION_MAJOR 1
#define SJCD_VERSION_MINOR 7
-#ifdef MODULE
#include <linux/module.h>
-#endif /* MODULE */
-
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mm.h>
@@ -1339,6 +1336,8 @@ int sjcd_open( struct inode *ip, struct file *fp ){
*/
if( fp->f_mode & 2 ) return( -EROFS );
+ MOD_INC_USE_COUNT;
+
if( sjcd_open_count == 0 ){
int s, sjcd_open_tries;
/* We don't know that, do we? */
@@ -1360,7 +1359,7 @@ int sjcd_open( struct inode *ip, struct file *fp ){
#if defined( SJCD_DIAGNOSTIC )
printk( "SJCD: open: timed out when check status.\n" );
#endif
- return( -EIO );
+ goto err_out;
} else if( !sjcd_media_is_available ){
#if defined( SJCD_DIAGNOSTIC )
printk("SJCD: open: no disk in drive\n");
@@ -1375,10 +1374,10 @@ int sjcd_open( struct inode *ip, struct file *fp ){
#if defined( SJCD_DIAGNOSTIC )
printk("SJCD: open: tray close attempt failed\n");
#endif
- return( -EIO );
+ goto err_out;
}
continue;
- } else return( -EIO );
+ } else goto err_out;
}
break;
}
@@ -1387,17 +1386,19 @@ int sjcd_open( struct inode *ip, struct file *fp ){
#if defined( SJCD_DIAGNOSTIC )
printk("SJCD: open: tray lock attempt failed\n");
#endif
- return( -EIO );
+ goto err_out;
}
#if defined( SJCD_TRACE )
printk( "SJCD: open: done\n" );
#endif
}
-#ifdef MODULE
- MOD_INC_USE_COUNT;
-#endif
+
++sjcd_open_count;
return( 0 );
+
+err_out:
+ MOD_DEC_USE_COUNT;
+ return( -EIO );
}
/*