summaryrefslogtreecommitdiffstats
path: root/drivers/cdrom
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-10-05 01:18:40 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-10-05 01:18:40 +0000
commit012bb3e61e5eced6c610f9e036372bf0c8def2d1 (patch)
tree87efc733f9b164e8c85c0336f92c8fb7eff6d183 /drivers/cdrom
parent625a1589d3d6464b5d90b8a0918789e3afffd220 (diff)
Merge with Linux 2.4.0-test9. Please check DECstation, I had a number
of rejects to fixup while integrating Linus patches. I also found that this kernel will only boot SMP on Origin; the UP kernel freeze soon after bootup with SCSI timeout messages. I commit this anyway since I found that the last CVS versions had the same problem.
Diffstat (limited to 'drivers/cdrom')
-rw-r--r--drivers/cdrom/cdrom.c72
-rw-r--r--drivers/cdrom/mcd.c4
-rw-r--r--drivers/cdrom/sbpcd.c117
-rw-r--r--drivers/cdrom/sbpcd.h1
-rw-r--r--drivers/cdrom/sonycd535.c12
5 files changed, 134 insertions, 72 deletions
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 4503bbfed..912402678 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -291,11 +291,13 @@ MODULE_PARM(check_media_type, "i");
#endif
/* These are used to simplify getting data in from and back to user land */
-#define IOCTL_IN(arg, type, in) \
- copy_from_user_ret(&in, (type *) arg, sizeof in, -EFAULT)
+#define IOCTL_IN(arg, type, in) \
+ if (copy_from_user(&in, (type *) arg, sizeof in)) \
+ return -EFAULT;
#define IOCTL_OUT(arg, type, out) \
- copy_to_user_ret((type *) arg, &out, sizeof out, -EFAULT)
+ if (copy_to_user((type *) 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. */
@@ -784,6 +786,8 @@ int cdrom_select_disc(struct cdrom_device_info *cdi, int slot)
if (!CDROM_CAN(CDC_SELECT_DISC))
return -EDRIVE_CANT_DO_THIS;
+ (void) cdi->ops->media_changed(cdi, slot);
+
if (slot == CDSL_NONE) {
/* set media changed bits, on both queues */
cdi->mc_flags = 0x3;
@@ -851,8 +855,8 @@ static int cdrom_media_changed(kdev_t dev)
if (cdi == NULL || cdi->ops->media_changed == NULL)
return 0;
if (!CDROM_CAN(CDC_MEDIA_CHANGED))
- return 0;
- return (media_changed(cdi, 0));
+ return 0;
+ return media_changed(cdi, 0);
}
/* badly broken, I know. Is due for a fixup anytime. */
@@ -872,8 +876,7 @@ void cdrom_count_tracks(struct cdrom_device_info *cdi, tracktype* tracks)
return;
}
/* 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 = cdi->ops->audio_ioctl(cdi, CDROMREADTOCHDR, &header))) {
if (ret == -ENOMEDIUM)
tracks->error = CDS_NO_DISC;
else
@@ -1115,6 +1118,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai)
cdinfo(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;
if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret;
@@ -1516,12 +1520,13 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
cdinfo(CD_DO_IOCTL, "entering CDROM_MEDIA_CHANGED\n");
if (!CDROM_CAN(CDC_MEDIA_CHANGED))
return -ENOSYS;
+
+ /* cannot select disc or select current disc */
if (!CDROM_CAN(CDC_SELECT_DISC) || arg == CDSL_CURRENT)
- /* cannot select disc or select current disc */
return media_changed(cdi, 1);
- if ((unsigned int)arg >= cdi->capacity) {
+
+ if ((unsigned int)arg >= cdi->capacity)
return -EINVAL;
- }
if ((ret = cdrom_read_mech_status(cdi, &info)))
return ret;
@@ -1570,10 +1575,10 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
if (!CDROM_CAN(CDC_SELECT_DISC))
return -ENOSYS;
- if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE)) {
- if ((int)arg >= cdi->capacity)
- return -EINVAL;
- }
+ if ((arg != CDSL_CURRENT) && (arg != CDSL_NONE))
+ if ((int)arg >= cdi->capacity)
+ return -EINVAL;
+
/* cdo->select_disc is a hook to allow a driver-specific
* way of seleting disc. However, since there is no
* equiv hook for cdrom_slot_status this may not
@@ -1601,8 +1606,9 @@ static int cdrom_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
if (!CDROM_CAN(CDC_LOCK))
return -EDRIVE_CANT_DO_THIS;
keeplocked = arg ? 1 : 0;
- /* don't unlock the door on multiple opens */
- if ((cdi->use_count != 1) && !arg)
+ /* don't unlock the door on multiple opens,but allow root
+ * to do so */
+ if ((cdi->use_count != 1) && !arg && !capable(CAP_SYS_ADMIN))
return -EBUSY;
return cdo->lock_door(cdi, arg);
}
@@ -1834,7 +1840,6 @@ 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;
@@ -1852,14 +1857,7 @@ static int cdrom_switch_blocksize(struct cdrom_device_info *cdi, int size)
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;
+ return cdo->generic_packet(cdi, &cgc);
}
static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
@@ -1916,16 +1914,10 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
}
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;
+ ret = -EFAULT;
kfree(cgc.buffer);
return ret;
}
@@ -1990,19 +1982,6 @@ static int mmc_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
/* cdinfo(CD_DO_IOCTL, "CDROMSUBCHNL successful\n"); */
return 0;
}
- case CDROMPLAYTRKIND: {
- struct cdrom_ti ti;
-
- cdinfo(CD_DO_IOCTL, "entering CDROMPLAYTRKIND\n");
- IOCTL_IN(arg, struct cdrom_ti, ti);
-
- 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: {
struct cdrom_msf msf;
cdinfo(CD_DO_IOCTL, "entering CDROMPLAYMSF\n");
@@ -2593,8 +2572,9 @@ static void cdrom_sysctl_register(void)
return;
cdrom_sysctl_header = register_sysctl_table(cdrom_root_table, 1);
+#ifdef CONFIG_PROC_FS
cdrom_root_table->child->de->owner = THIS_MODULE;
-
+#endif /* CONFIG_PROC_FS */
/* set the defaults */
cdrom_sysctl_settings.autoclose = autoclose;
cdrom_sysctl_settings.autoeject = autoeject;
diff --git a/drivers/cdrom/mcd.c b/drivers/cdrom/mcd.c
index c44546274..b064b2e22 100644
--- a/drivers/cdrom/mcd.c
+++ b/drivers/cdrom/mcd.c
@@ -275,7 +275,7 @@ static int mcd_media_changed(struct cdrom_device_info * cdi, int disc_nr)
static int
statusCmd(void)
{
- int st, retry;
+ int st = -1, retry;
for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
{
@@ -297,7 +297,7 @@ statusCmd(void)
static int
mcdPlay(struct mcd_Play_msf *arg)
{
- int retry, st;
+ int retry, st = -1;
for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
{
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index df2174a8c..07e97a1d7 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -1,3 +1,5 @@
+
+
/*
* sbpcd.c CD-ROM device driver for the whole family of traditional,
* non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives.
@@ -13,7 +15,7 @@
* labelled E2550UA or MK4015 or 2800F).
*/
-#define VERSION "v4.61 Eberhard Moenkeberg <emoenke@gwdg.de>"
+#define VERSION "v4.63 Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000"
/* Copyright (C) 1993, 1994, 1995 Eberhard Moenkeberg <emoenke@gwdg.de>
*
@@ -46,7 +48,7 @@
*
* 0.1 initial release, April/May 93, after mcd.c (Martin Harriss)
*
- * 0.2 the "repeat:"-loop in do_sbpcd_request did not check for
+ * 0.2 thek "repeat:"-loop in do_sbpcd_request did not check for
* end-of-request_queue (resulting in kernel panic).
* Flow control seems stable, but throughput is not better.
*
@@ -312,9 +314,20 @@
* module_init & module_exit.
* Torben Mathiasen <tmm@image.dk>
*
+ * 4.63 Bug fixes for audio annoyances, new legacy CDROM maintainer.
+ * Annoying things fixed:
+ * TOC reread on automated disk changes
+ * TOC reread on manual cd changes
+ * Play IOCTL tries to play CD before it's actually ready... sometimes.
+ * CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play.
+ * Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000
+ *
*
* TODO
* implement "read all subchannel data" (96 bytes per frame)
+ * remove alot of the virtual status bits and deal with hardware status
+ * move the change of cd for audio to a better place
+ * add debug levels to insmod parameters (trivial)
*
* special thanks to Kai Makisara (kai.makisara@vtt.fi) for his fine
* elaborated speed-up experiments (and the fabulous results!), for
@@ -637,9 +650,9 @@ static u_int maxtim_data= 9000;
static u_int maxtim_data= 3000;
#endif LONG_TIMING
#if DISTRIBUTION
-static int n_retries=3;
+static int n_retries=6;
#else
-static int n_retries=1;
+static int n_retries=6;
#endif
/*==========================================================================*/
@@ -2046,7 +2059,9 @@ static int DriveReset(void)
do
{
i=GetStatus();
- if ((i<0)&&(i!=-ERR_DISKCHANGE)) return (-2); /* from sta2err */
+ if ((i<0)&&(i!=-ERR_DISKCHANGE)) {
+ return (-2); /* from sta2err */
+ }
if (!st_caddy_in) break;
sbp_sleep(1);
}
@@ -2343,16 +2358,21 @@ static int cc_CloseTray(void)
static int sbpcd_tray_move(struct cdrom_device_info *cdi, int position)
{
- int i;
- i = MINOR(cdi->dev);
-
- switch_drive(i);
- if (position == 1) {
- cc_SpinDown();
- } else {
- return cc_CloseTray();
- }
- return 0;
+ int i;
+ int retval=0;
+ i = MINOR(cdi->dev);
+ switch_drive(i);
+ /* DUH! --AJK */
+ if(D_S[d].CD_changed != 0xFF) {
+ D_S[d].CD_changed=0xFF;
+ D_S[d].diskstate_flags &= ~cd_size_bit;
+ }
+ if (position == 1) {
+ cc_SpinDown();
+ } else {
+ retval=cc_CloseTray();
+ }
+ return retval;
}
/*==========================================================================*/
@@ -4023,6 +4043,7 @@ static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
+
#if 0
if (!(D_S[MINOR(cdi->dev)].status_bits & p_door_closed)) return CDS_TRAY_OPEN;
if (D_S[MINOR(cdi->dev)].status_bits & p_disk_ok) return CDS_DISC_OK;
@@ -4031,8 +4052,11 @@ static int sbpcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
return CDS_NO_DISC;
#else
if (D_S[MINOR(cdi->dev)].status_bits & p_spinning) return CDS_DISC_OK;
- return CDS_TRAY_OPEN;
+/* return CDS_TRAY_OPEN; */
+ return CDS_NO_DISC;
+
#endif
+
}
@@ -4500,7 +4524,7 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
void * arg)
{
- int i, st;
+ int i, st, j;
msg(DBG_IO2,"ioctl(%d, 0x%08lX, 0x%08p)\n",
MINOR(cdi->dev), cmd, arg);
@@ -4696,19 +4720,68 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
case CDROMSUBCHNL: /* Get subchannel info */
msg(DBG_IOS,"ioctl: CDROMSUBCHNL entered.\n");
+ /* Bogus, I can do better than this! --AJK
if ((st_spinning)||(!subq_valid)) {
i=cc_ReadSubQ();
if (i<0) RETURN_UP(-EIO);
}
+ */
+ i=cc_ReadSubQ();
+ if (i<0) {
+ j=cc_ReadError(); /* clear out error status from drive */
+ D_S[d].audio_state=CDROM_AUDIO_NO_STATUS;
+ /* get and set the disk state here,
+ probably not the right place, but who cares!
+ It makes it work properly! --AJK */
+ if (D_S[d].CD_changed==0xFF) {
+ msg(DBG_000,"Disk changed detect\n");
+ D_S[d].diskstate_flags &= ~cd_size_bit;
+ }
+ RETURN_UP(-EIO);
+ }
+ if (D_S[d].CD_changed==0xFF) {
+ /* reread the TOC because the disk has changed! --AJK */
+ msg(DBG_000,"Disk changed STILL detected, rereading TOC!\n");
+ i=DiskInfo();
+ if(i==0) {
+ D_S[d].CD_changed=0x00; /* cd has changed, procede, */
+ RETURN_UP(-EIO); /* and get TOC, etc on next try! --AJK */
+ } else {
+ RETURN_UP(-EIO); /* we weren't ready yet! --AJK */
+ }
+ }
memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
+ /*
+ This virtual crap is very bogus!
+ It doesn't detect when the cd is done playing audio!
+ Lets do this right with proper hardware register reading!
+ */
+ cc_ReadStatus();
+ i=ResponseStatus();
+ msg(DBG_000,"Drive Status: door_locked =%d.\n", st_door_locked);
+ msg(DBG_000,"Drive Status: door_closed =%d.\n", st_door_closed);
+ msg(DBG_000,"Drive Status: caddy_in =%d.\n", st_caddy_in);
+ msg(DBG_000,"Drive Status: disk_ok =%d.\n", st_diskok);
+ msg(DBG_000,"Drive Status: spinning =%d.\n", st_spinning);
+ msg(DBG_000,"Drive Status: busy =%d.\n", st_busy);
+ /* st_busy indicates if it's _ACTUALLY_ playing audio */
switch (D_S[d].audio_state)
{
case audio_playing:
- SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
+ if(st_busy==0) {
+ /* CD has stopped playing audio --AJK */
+ D_S[d].audio_state=audio_completed;
+ SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
+ } else {
+ SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
+ }
break;
case audio_pausing:
SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
break;
+ case audio_completed:
+ SC.cdsc_audiostatus=CDROM_AUDIO_COMPLETED;
+ break;
default:
SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
break;
@@ -5883,6 +5956,14 @@ static int sbpcd_chk_disk_change(kdev_t full_dev)
{
D_S[i].CD_changed=0;
msg(DBG_CHK,"medium changed (drive %d)\n", i);
+ /* BUG! Should invalidate buffers! --AJK */
+ invalidate_buffers(full_dev);
+ D_S[d].diskstate_flags &= ~toc_bit;
+ D_S[d].diskstate_flags &= ~cd_size_bit;
+#if SAFE_MIXED
+ D_S[d].has_data=0;
+#endif SAFE_MIXED
+
return (1);
}
else
diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h
index 805e98a82..6632fa48c 100644
--- a/drivers/cdrom/sbpcd.h
+++ b/drivers/cdrom/sbpcd.h
@@ -412,6 +412,7 @@
/*
* audio states:
*/
+#define audio_completed 3 /* Forgot this one! --AJK */
#define audio_playing 2
#define audio_pausing 1
diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c
index 8349e5928..15bcacd85 100644
--- a/drivers/cdrom/sonycd535.c
+++ b/drivers/cdrom/sonycd535.c
@@ -217,16 +217,16 @@ static unsigned short command_reg;
static unsigned short read_status_reg;
static unsigned short data_reg;
-static int initialized = 0; /* Has the drive been initialized? */
+static int initialized; /* Has the drive been initialized? */
static int sony_disc_changed = 1; /* Has the disk been changed
since the last check? */
-static int sony_toc_read = 0; /* Has the table of contents been
+static int sony_toc_read; /* Has the table of contents been
read? */
static unsigned int sony_buffer_size; /* Size in bytes of the read-ahead
buffer. */
static unsigned int sony_buffer_sectors; /* Size (in 2048 byte records) of
the read-ahead buffer. */
-static unsigned int sony_usage = 0; /* How many processes have the
+static unsigned int sony_usage; /* How many processes have the
drive open. */
static int sony_first_block = -1; /* First OS block (512 byte) in
@@ -242,7 +242,7 @@ static struct s535_sony_subcode *last_sony_subcode; /* Points to the last
static Byte **sony_buffer; /* Points to the pointers
to the sector buffers */
-static int sony_inuse = 0; /* is the drive in use? Only one
+static int sony_inuse; /* is the drive in use? Only one
open at a time allowed */
/*
@@ -260,8 +260,8 @@ static int sony_audio_status = CDROM_AUDIO_NO_STATUS;
* I just kept the CDU-31A driver behavior rather than using the PAUSE
* command on the CDU-535.
*/
-static Byte cur_pos_msf[3] = {0, 0, 0};
-static Byte final_pos_msf[3] = {0, 0, 0};
+static Byte cur_pos_msf[3];
+static Byte final_pos_msf[3];
/* What IRQ is the drive using? 0 if none. */
static int sony535_irq_used = CDU535_INTERRUPT;