[208] in linux-announce channel archive
mcd driver enhancements - please test ...
daemon@ATHENA.MIT.EDU (Lars Wirzenius)
Sun Feb 19 14:48:46 1995
Date: Sun, 19 Feb 1995 19:52:40 +0200
From: Lars Wirzenius <wirzeniu@cc.helsinki.fi>
To: linux-activists@niksula.hut.fi, linux-announce@vger.rutgers.edu
X-Mn-Key: announce
Subject: mcd driver enhancements - please test ...
From: becka@hp817S.rz.uni-duesseldorf.de
Newsgroups: comp.os.linux.announce
Keywords: mcd, Mitsumi, CD-ROM, device driver, Linux kernel
Organization: ?
Approved: linux-announce@tc.cornell.edu (Lars Wirzenius)
Followup-to: comp.os.linux.development.system
Hello everybody using a Mitsumi CD-ROM driven by mcd.c (i.e. not the new
ATAPI ones)
I already asked Linus to make the attached patches part of the standard
kernel,but he would like to have them tested by a larger part of the Linux
community - so I need your help ...
Please test the patches attached below and send me mail whether they work
on your system.
I have added some additional functionality to the Mitsumi cdrom-driver :
The FX-Series drives have some additional capabilities,which I wanted to have
supported - door-locking,a software controlled tray mechanism and volume
control.
I had success with the first two,but volume control seems to be extremely
limited,but from what I discovered by disassembling the MS-DOS driver,I
think this is a Hardware-Restriction.
Anyway the volctrl code now works (tested with workman),but it only allows
the volumes 0 and !=0 to be set what results in no or full volume
respectively ... maybe someone with another drive should see if it works for
him (the code should be right - maybe there is a drive out there that really
supports setting the volume).
P.S.: I've seen,that this code changed in the last kernel,but IMHO the
change is wrong - mine should be correct (it is derived from the DOS driver
function for setting the volume ...)
The door of the FX-series drives is now locked in mcd_open and released in
mcd_release,so you cannot open the tray manually while the cdrom is
mounted.
When opening the device,the driver now checks for "door open" and tries to
close it - this has a 5 second timeout that might be undesireable on drives
that don't support the CLOSE_TRAY function.Maybe someone could add specific
code to distinguish the drives by their version code,as I don't know anything
of the other drives.
My code should be pretty straightforward,so you should have no problems
patching it in all recent kernels (1.1.89 and up might require some minor
changes due to the change I mentioned above).
I will have a look at the DMA-based driver (that didn't work for me until I
changed my hardware ...) ASAP to see,if it could be ported to Linux.
I suppose this will increase responsiveness of the cdrom and might even
allow readaheads what would be quite useful with several programs playing
multimedia data directly from the drive.
O.K. the diffs are attached below - if you've got any questions on them
please mail me at <becka@hp.rz.uni-duesseldorf.de>
TNX 4 your efforts,
Andy
-----------------------------------------------------------------------------
--- mcd.old Thu Aug 4 17:33:54 1994
+++ mcd.c Tue Aug 16 01:27:51 1994
@@ -26,10 +26,12 @@
0.3 Audio support added
0.3.1 Changes for mitsumi CRMC LU005S march version
(stud11@cc4.kuleuven.ac.be)
- 0.3.2 bug fixes to the ioclts and merged with ALPHA0.99-pl12
+ 0.3.2 bug fixes to the ioctls and merged with ALPHA0.99-pl12
(Jon Tombs <jon@robots.ox.ac.uk>)
0.3.3 Added more #defines and mcd_setup()
(Jon Tombs <jon@gtex02.us.es>)
+ 0.3.3a Added support for door-locking and CD-"uneject" for FX series
+ drives (Andreas Beck <becka@hp.rz.uni-duesseldorf.de>)
October 1993 Bernd Huebner and Ruediger Helsch, Unifix Software GmbH,
Braunschweig, Germany: Total rework to speed up data read operation.
@@ -74,6 +76,9 @@
#define TEST5 */ /* port(1) state */
#endif
+#define CLOSE_DOOR_RETRY 5
+#define CLOSE_DOOR_DELAY 100
+
#if 1
#define QUICK_LOOP_DELAY udelay(45) /* use udelay */
#define QUICK_LOOP_COUNT 20
@@ -143,8 +148,16 @@
static int GetDiskInfo(void);
static int GetToc(void);
static int getValue(unsigned char *result);
-
+static int mcd_close_tray_wait(void);
+static int mcd_lock_door(int lock);
+static inline void mcd_sleep(u_int jifs)
+{
+ current->state = TASK_INTERRUPTIBLE;
+ current->timeout = jiffies + jifs;
+ schedule();
+}
+
void mcd_setup(char *str, int *ints)
{
if (ints[0] > 0)
@@ -247,7 +260,7 @@
struct cdrom_tocentry entry;
struct mcd_Toc *tocPtr;
struct cdrom_subchnl subchnl;
-#if 0
+#if 1
struct cdrom_volctrl volctrl;
#endif
@@ -492,59 +505,63 @@
case CDROMVOLCTRL: /* Volume control */
/*
- * This is not working yet. Setting the volume by itself does
- * nothing. Following the 'set' by a 'play' results in zero
- * volume. Something to work on for the next release.
+ * This is working yet. But there are only two possible values :
+ * 0 and !0 for silence or full volume ... seems this is a hardware
+ * restriction ...
*/
-#if 0
+#if 1
st = verify_area(VERIFY_READ, (void *) arg, sizeof(volctrl));
if (st)
return st;
memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
-printk("VOL %d %d\n", volctrl.channel0 & 0xFF, volctrl.channel1 & 0xFF);
outb(MCMD_SET_VOLUME, MCDPORT(0));
outb(volctrl.channel0, MCDPORT(0));
outb(0, MCDPORT(0));
outb(volctrl.channel1, MCDPORT(0));
- outb(1, MCDPORT(0));
+ outb(0, MCDPORT(0));
i = getMcdStatus(MCD_STATUS_DELAY);
- if (i < 0)
+ if (i ==-1)
return -EIO;
- {
- int a, b, c, d;
-
+ { /* Did the drive get the correct values ? */
+ /* the GetValues are necessary - maybe we replace
+ them by 4 times getValue(&dummy) later ... */
+ unsigned char a, b, c, d;
getValue(&a);
getValue(&b);
getValue(&c);
getValue(&d);
- printk("%02X %02X %02X %02X\n", a, b, c, d);
+ if (a!=volctrl.channel0||c!=volctrl.channel1)
+ return -EAGAIN;
}
- outb(0xF8, MCDPORT(0));
- i = getMcdStatus(MCD_STATUS_DELAY);
- printk("F8 -> %02X\n", i & 0xFF);
#endif
return 0;
case CDROMEJECT:
- /* all drives can atleast stop! */
- if (audioStatus == CDROM_AUDIO_PLAY) {
- outb(MCMD_STOP, MCDPORT(0));
+ if (st&MST_DOOR_OPEN) { /* The door IS open - we
+ i=mcd_close_tray_wait(); should try to close it */
+ }
+ else
+ {
+ /* all drives can at least stop! */
+ if (audioStatus == CDROM_AUDIO_PLAY) {
+ outb(MCMD_STOP, MCDPORT(0));
+ i = getMcdStatus(MCD_STATUS_DELAY);
+ }
+
+ audioStatus = CDROM_AUDIO_NO_STATUS;
+
+ outb(MCMD_EJECT, MCDPORT(0));
+ /*
+ * the status (i) shows failure on all but the FX drives.
+ * But nothing we can do about that in software!
+ * So just read the status and forget it. - Jon.
+ */
i = getMcdStatus(MCD_STATUS_DELAY);
}
-
- audioStatus = CDROM_AUDIO_NO_STATUS;
-
- outb(MCMD_EJECT, MCDPORT(0));
- /*
- * the status (i) shows failure on all but the FX drives.
- * But nothing we can do about that in software!
- * So just read the status and forget it. - Jon.
- */
- i = getMcdStatus(MCD_STATUS_DELAY);
return 0;
default:
return -EINVAL;
@@ -1017,12 +1034,46 @@
mcd_buf_out = -1;
}
+static int
+mcd_close_tray(void)
+{ outb(MCMD_CLOSE, MCDPORT(0));
+ return(getMcdStatus(MCD_STATUS_DELAY));
+}
+
+static int
+mcd_close_tray_wait(void)
+{
+ int retry,st;
+
+ st = statusCmd(); /* check drive status */
+ if (st == -1) return st; /* drive doesn't respond */
+
+ if ((st & MST_DOOR_OPEN))
+ {
+ printk("mcd: door open - trying to close\n");
+ mcd_close_tray();
+ for(retry=0;((st = statusCmd())&MST_READY)==0
+ &&retry<CLOSE_DOOR_RETRY;retry++)
+ { /* wait for tray 3 secs max. */
+ printk("mcd: status while waiting for ready %x\n",st);
+ mcd_sleep(CLOSE_DOOR_DELAY); }
+ }
+
+ return st;
+}
+
+static int
+mcd_lock_door(int lock)
+{ outb(MCMD_LOCK, MCDPORT(0));
+ outb(lock , MCDPORT(0));
+ return(getMcdStatus(MCD_STATUS_DELAY));
+}
/*
* Open the device special file. Check that a disk is in.
*/
-int
+static int
mcd_open(struct inode *ip, struct file *fp)
{
int st;
@@ -1037,11 +1088,12 @@
mcd_invalidate_buffers();
- st = statusCmd(); /* check drive status */
+ st = mcd_close_tray_wait(); /* close tray if necessary
+ and check drive status */
if (st == -1)
return -EIO; /* drive doesn't respond */
- if ((st & MST_READY) == 0) /* no disk in drive */
+ if ((st & MST_READY) == 0)/* no disk in drive */
{
printk("mcd: no disk in drive\n");
return -EIO;
@@ -1052,6 +1104,7 @@
}
++mcd_open_count;
+ mcd_lock_door(1);
return 0;
}
@@ -1068,6 +1121,7 @@
mcd_invalidate_buffers();
sync_dev(inode->i_rdev);
invalidate_buffers(inode -> i_rdev);
+ mcd_lock_door(0);
}
}
@@ -1363,7 +1405,7 @@
* table of contents.
*/
-int
+static int
GetQChannelInfo(struct mcd_Toc *qp)
{
unsigned char notUsed;
--- mcd.hold Thu Aug 4 17:40:48 1994
+++ /usr/include/linux/mcd.h Thu Aug 4 17:42:00 1994
@@ -65,6 +65,8 @@
#define MCMD_PLAY_READ 0xC0 /* play or read data */
#define MCMD_GET_VERSION 0xDC
#define MCMD_EJECT 0xF6 /* eject (FX drive) */
+#define MCMD_CLOSE 0xF8 /* close tray (FX) */
+#define MCMD_LOCK 0xFE /* (un)lock door (FX) */
/* borrowed from hd.c */
--
==============================================================================
Andreas Beck | Email : <becka@hp.rz.uni-duesseldorf.de>
Zur Goetscher Muehle 25 | Phone : +49 2173 72916
D-40764 Langenfeld | Fax : +49 2173 83563
==============================================================================
--
Send submissions for comp.os.linux.announce to: linux-announce@news.ornl.gov
PLEASE remember Keywords: and a short description of the software.