patch-1.3.39 linux/drivers/cdrom/mcd.c
Next file: linux/drivers/cdrom/mcdx.c
Previous file: linux/drivers/cdrom/gscd.c
Back to the patch index
Back to the overall index
- Lines: 210
- Date:
Thu Nov 9 09:47:18 1995
- Orig file:
v1.3.38/linux/drivers/cdrom/mcd.c
- Orig date:
Mon Oct 23 18:02:05 1995
diff -u --recursive --new-file v1.3.38/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c
@@ -59,22 +59,21 @@
DOS DRIVERS .... Accuracy counts... speed is secondary ;)
17 June 95 Modifications By Andrew J. Kroll <ag784@freenet.buffalo.edu>
07 July 1995 Modifications by Andrew J. Kroll
+
+ 0.6
+ 8 November 95 More Modifications By Andrew J. Kroll
+ Media change detect now works :) That means that SuperMount and
+ other programs that depend on this will now work!
+ You are welcome in advance! You will notice, however that you don't
+ always get the kernel message saying "VFS: Disk change detected on
+ device", so I'm not sure that it's *PERFECT* but it does seem to
+ actually work! What else should I add?
+
*/
-#include <linux/config.h>
-#ifdef MODULE
-# include <linux/module.h>
-# include <linux/version.h>
-# ifndef CONFIG_MODVERSIONS
- char kernel_version[]= UTS_RELEASE;
-# endif
-#define mcd_init init_module
-#else
-# define MOD_INC_USE_COUNT
-# define MOD_DEC_USE_COUNT
-#endif
+#include <linux/module.h>
#include <linux/errno.h>
#include <linux/signal.h>
@@ -145,18 +144,22 @@
#define MFL_STATUSorDATA (MFL_STATUS | MFL_DATA)
#define MCD_BUF_SIZ 16
static volatile int mcd_transfer_is_active;
+
+/* Are you sleeping, Are you sleeping, Brother John, Brother John? ;) */
+static volatile int sleeping_for_status;
+
static char mcd_buf[2048*MCD_BUF_SIZ]; /* buffer for block size conversion */
static volatile int mcd_buf_bn[MCD_BUF_SIZ], mcd_next_bn;
static volatile int mcd_buf_in, mcd_buf_out = -1;
static volatile int mcd_error;
static int mcd_open_count;
enum mcd_state_e {
- MCD_S_IDLE, /* 0 */
- MCD_S_START, /* 1 */
- MCD_S_MODE, /* 2 */
- MCD_S_READ, /* 3 */
- MCD_S_DATA, /* 4 */
- MCD_S_STOP, /* 5 */
+ MCD_S_IDLE, /* 0 */
+ MCD_S_START, /* 1 */
+ MCD_S_MODE, /* 2 */
+ MCD_S_READ, /* 3 */
+ MCD_S_DATA, /* 4 */
+ MCD_S_STOP, /* 5 */
MCD_S_STOPPING /* 6 */
};
static volatile enum mcd_state_e mcd_state = MCD_S_IDLE;
@@ -211,31 +214,7 @@
mitsumi_bug_93_wait = ints[3];
#endif /* WORK_AROUND_MITSUMI_BUG_93 */
}
-
-static int
-check_mcd_change(kdev_t full_dev)
-{
- int retval, target;
-
-
-#if 1 /* the below is not reliable */
- return 0;
-#endif
- target = MINOR(full_dev);
-
- if (target > 0) {
- printk("mcd: Mitsumi CD-ROM request error: invalid device.\n");
- return 0;
- }
-
- retval = mcdDiskChanged;
- mcdDiskChanged = 0;
-
- return retval;
-}
-
-
/*
* Do a 'get status' command and get the result. Only use from the top half
* because it calls 'getMcdStatus' which sleeps.
@@ -258,6 +237,69 @@
return st;
}
+/*
+ * This detects a media change on the CD ROM.
+ * We need to grab the status right off the drive in here.
+ * Before, it ALWAYS returned a value of 0, which was not right!
+ */
+
+static int
+check_mcd_change(dev_t full_dev)
+{
+ int retval, target, st, count;
+ st = -1;
+ target = MINOR(full_dev);
+
+ if (target > 0)
+ {
+ printk("mcd: Mitsumi CD-ROM request error: invalid device.\n");
+ return 0;
+ }
+
+/*
+ * SOMETIMES it changes, sometimes not! Well, here we FIX that little nasty!
+ * All we need to do is read the status from the drive without spamming the
+ * kernel! In other words, this routine CANNOT sleep!
+ * The kernel will automagically picks up on this now.
+ * Devilishly sneaky it is! 8) -- AJK
+ */
+if ((!mcd_transfer_is_active) &&
+ (!sleeping_for_status) &&
+ (mcd_state == MCD_S_IDLE)) /* YES I'm paraniod! :) */
+ {
+ outb(MCMD_GET_STATUS, MCDPORT(0)); /* send get-status cmd */
+ for (count = 0; count < 3000; count++) /* wait for the status */
+ {
+ if (!(inb(MCDPORT(1)) & MFL_STATUS))
+ break;
+ }
+ if (count >= 3000) /* Did we time out? */
+ {
+ retval = mcdDiskChanged; /* We can just jump out of here */
+ mcdDiskChanged = 0; /* as it's not needed all the time. */
+ return retval; /* So we pretend nothing happened here! ;) */
+ }
+ st=inb(MCDPORT(0)) & 0xFF ; /* Read the status in... */
+
+ /* okay... here's that magic part! Muhuhuhuh...*/
+
+ if (st & MST_DSK_CHG) /* Devil made me do it! O];) */
+ {
+ mcdDiskChanged = 1; /* Show a change. */
+ audioStatus = CDROM_AUDIO_NO_STATUS; /* just incase... */
+ tocUpToDate = 0; /* Frantic laughing continues... */
+ mcd_invalidate_buffers(); /* 666 wins! */
+ } /* Stupid comments are fun! */
+
+
+ }
+
+ retval = mcdDiskChanged; /* Indicate status. */
+ mcdDiskChanged = 0; /* Go, now. Enjoy a good beer! */
+
+ return retval; /* The End. */
+}
+
/*
* Send a 'Play' command and get the status. Use only from the top half.
@@ -1175,7 +1217,7 @@
{
int count;
unsigned char result[3];
-
+ sleeping_for_status = 0;
if (mcd_port <= 0 || mcd_irq <= 0) {
printk("skip mcd_init\n");
return -EIO;
@@ -1377,10 +1419,14 @@
McdTimeout = timeout;
SET_TIMER(mcdStatTimer, 1);
- sleep_on(&mcd_waitq);
+ sleeping_for_status = 1;
+ sleep_on(&mcd_waitq);
if (McdTimeout <= 0)
- return -1;
-
+ {
+ sleeping_for_status = 0;
+ return -1;
+ }
+ sleeping_for_status = 0;
st = inb(MCDPORT(0)) & 0xFF;
if (st == 0xFF)
return -1;
@@ -1616,11 +1662,13 @@
}
#ifdef MODULE
+int init_module(void)
+{
+ return mcd_init();
+}
+
void cleanup_module(void)
-{ if (MOD_IN_USE)
- { printk("mcd module in use - can't remove it.\n");
- return;
- }
+{
if ((unregister_blkdev(MAJOR_NR, "mcd") == -EINVAL))
{ printk("What's that: can't unregister mcd\n");
return;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this