patch-2.1.70 linux/drivers/cdrom/mcdx.c
Next file: linux/drivers/cdrom/mcdx.h
Previous file: linux/drivers/cdrom/mcd.h
Back to the patch index
Back to the overall index
- Lines: 1044
- Date:
Tue Dec 2 11:41:44 1997
- Orig file:
v2.1.69/linux/drivers/cdrom/mcdx.c
- Orig date:
Wed Sep 24 20:05:46 1997
diff -u --recursive --new-file v2.1.69/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c
@@ -73,7 +73,10 @@
/* for compatible parameter passing with "insmod" */
#define mcdx_drive_map mcdx
-#include <linux/mcdx.h>
+#include "mcdx.h"
+
+#define MCDX_QUIET 0
+
#ifndef HZ
#error HZ not defined
@@ -107,8 +110,6 @@
const int REQUEST_SIZE = 800; /* should be less then 255 * 4 */
const int DIRECT_SIZE = 400; /* should be less then REQUEST_SIZE */
-const unsigned long ACLOSE_INHIBIT = 800; /* 1/100 s of autoclose inhibit */
-
enum drivemodes { TOC, DATA, RAW, COOKED };
enum datamodes { MODE0, MODE1, MODE2 };
enum resetmodes { SOFT, HARD };
@@ -160,8 +161,6 @@
volatile int introk; /* status of last irq operation */
volatile int busy; /* drive performs an operation */
volatile int lock; /* exclusive usage */
- int eject_sw; /* 1 - eject on last close (default 0) */
- int autoclose; /* 1 - close the door on open (default 1) */
/* cd infos */
struct s_diskinfo di;
@@ -197,7 +196,6 @@
unsigned char playcmd; /* play should always be single speed */
unsigned int xxx; /* set if changed, reset while open */
unsigned int yyy; /* set if changed, reset by media_changed */
- unsigned long ejected; /* time we called the eject function */
int users; /* keeps track of open/close */
int lastsector; /* last block accessible */
int status; /* last operation's error / status */
@@ -214,22 +212,25 @@
/* declared in blk.h */
int mcdx_init(void);
void do_mcdx_request(void);
-int check_mcdx_media_change(kdev_t);
/* already declared in init/main */
void mcdx_setup(char *, int *);
/* Indirect exported functions. These functions are exported by their
addresses, such as mcdx_open and mcdx_close in the
- structure fops. */
+ structure mcdx_dops. */
/* ??? exported by the mcdx_sigaction struct */
static void mcdx_intr(int, void *, struct pt_regs*);
/* exported by file_ops */
-static int mcdx_open(struct inode*, struct file*);
-static int mcdx_close(struct inode*, struct file*);
-static int mcdx_ioctl(struct inode*, struct file*, unsigned int, unsigned long);
+static int mcdx_open(struct cdrom_device_info * cdi, int purpose);
+static void mcdx_close(struct cdrom_device_info * cdi);
+static int mcdx_media_changed(struct cdrom_device_info * cdi, int disc_nr);
+static int mcdx_tray_move(struct cdrom_device_info * cdi, int position);
+static int mcdx_lockdoor(struct cdrom_device_info * cdi, int lock);
+static int mcdx_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd,
+ void * arg);
/* misc internal support functions */
static void log2msf(unsigned int, struct cdrom_msf0*);
@@ -243,13 +244,10 @@
static int mcdx_xfer(struct s_drive_stuff*, char* buf, int sector, int nr_sectors);
static int mcdx_config(struct s_drive_stuff*, int);
-static int mcdx_closedoor(struct s_drive_stuff*, int);
static int mcdx_requestversion(struct s_drive_stuff*, struct s_version*, int);
-static int mcdx_lockdoor(struct s_drive_stuff*, int, int);
static int mcdx_stop(struct s_drive_stuff*, int);
static int mcdx_hold(struct s_drive_stuff*, int);
static int mcdx_reset(struct s_drive_stuff*, enum resetmodes, int);
-static int mcdx_eject(struct s_drive_stuff*, int);
static int mcdx_setdrivemode(struct s_drive_stuff*, enum drivemodes, int);
static int mcdx_setdatamode(struct s_drive_stuff*, enum datamodes, int);
static int mcdx_requestsubqcode(struct s_drive_stuff*, struct s_subqcode*, int);
@@ -276,37 +274,79 @@
0, 0, 0, 0, 0, 0, 0, 0};
MODULE_PARM(mcdx, "1-4i");
-static struct file_operations mcdx_fops = {
- NULL, /* lseek - use kernel default */
- block_read, /* read - general block-dev read */
- block_write, /* write - general block-dev write */
- NULL, /* no readdir */
- NULL, /* no poll */
- mcdx_ioctl, /* ioctl() */
- NULL, /* no mmap */
- mcdx_open, /* open() */
- mcdx_close, /* close() */
- NULL, /* fsync */
- NULL, /* fasync */
- check_mcdx_media_change, /* media_change */
- NULL /* revalidate */
+static struct cdrom_device_ops mcdx_dops = {
+ mcdx_open, /* open */
+ mcdx_close, /* release */
+ NULL, /* drive status */
+ mcdx_media_changed, /* media changed */
+ mcdx_tray_move, /* tray move */
+ mcdx_lockdoor, /* lock door */
+ NULL, /* select speed */
+ NULL, /* select disc */
+ NULL, /* get last session */
+ NULL, /* get universal product code */
+ NULL, /* hard reset */
+ mcdx_audio_ioctl, /* audio ioctl */
+ NULL, /* device-specific ioctl */
+ CDC_OPEN_TRAY | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO
+ | CDC_DRIVE_STATUS, /* capability */
+ 0, /* number of minor devices */
+};
+
+static struct cdrom_device_info mcdx_info = {
+ &mcdx_dops, /* device operations */
+ NULL, /* link */
+ NULL, /* handle */
+ MKDEV(MAJOR_NR,0), /* dev */
+ 0, /* mask */
+ 2, /* maximum speed */
+ 1, /* number of discs */
+ 0, /* options, not owned */
+ 0, /* mc_flags, not owned */
+ 0, /* use count, not owned */
+ "mcdx", /* name of the device type */
};
+
+
/* KERNEL INTERFACE FUNCTIONS **************************************/
-static int
-mcdx_ioctl(
- struct inode* ip, struct file* fp,
- unsigned int cmd, unsigned long arg)
+
+static int mcdx_audio_ioctl(struct cdrom_device_info * cdi, unsigned int cmd,
+ void * arg)
{
- struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(ip->i_rdev)];
+ struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
if (!stuffp->present) return -ENXIO;
- if (!ip) return -EINVAL;
+
+ if (stuffp->xxx)
+ {
+ if(-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1))
+ {
+ stuffp->lastsector = -1;
+ }
+ else
+ {
+ stuffp->lastsector = (CD_FRAMESIZE / 512)
+ * msf2log(&stuffp->di.msf_leadout) - 1;
+ }
+
+ if (stuffp->toc)
+ {
+ kfree(stuffp->toc);
+ stuffp->toc = NULL;
+ if (-1 == mcdx_readtoc(stuffp)) return -1;
+ }
+
+ stuffp->xxx=0;
+ }
switch (cmd) {
- case CDROMSTART: {
- xtrace(IOCTL, "ioctl() START\n");
+ case CDROMSTART: {
+ xtrace(IOCTL, "ioctl() START\n");
+ /* Spin up the drive. Don't think we can do this.
+ * For now, ignore it.
+ */
return 0;
}
@@ -319,51 +359,40 @@
}
case CDROMPLAYTRKIND: {
- int ans;
- struct cdrom_ti ti;
+ struct cdrom_ti *ti=(struct cdrom_ti *) arg;
xtrace(IOCTL, "ioctl() PLAYTRKIND\n");
- if ((ans = verify_area(VERIFY_READ, (void*) arg, sizeof(ti))))
- return ans;
- copy_from_user(&ti, (void*) arg, sizeof(ti));
- if ((ti.cdti_trk0 < stuffp->di.n_first)
- || (ti.cdti_trk0 > stuffp->di.n_last)
- || (ti.cdti_trk1 < stuffp->di.n_first))
- return -EINVAL;
- if (ti.cdti_trk1 > stuffp->di.n_last) ti.cdti_trk1 = stuffp->di.n_last;
- xtrace(PLAYTRK, "ioctl() track %d to %d\n", ti.cdti_trk0, ti.cdti_trk1);
-
- return mcdx_playtrk(stuffp, &ti);
+ if ((ti->cdti_trk0 < stuffp->di.n_first)
+ || (ti->cdti_trk0 > stuffp->di.n_last)
+ || (ti->cdti_trk1 < stuffp->di.n_first))
+ return -EINVAL;
+ if (ti->cdti_trk1 > stuffp->di.n_last)
+ ti->cdti_trk1 = stuffp->di.n_last;
+ xtrace(PLAYTRK, "ioctl() track %d to %d\n", ti->cdti_trk0, ti->cdti_trk1);
+ return mcdx_playtrk(stuffp, ti);
}
case CDROMPLAYMSF: {
- int ans;
- struct cdrom_msf msf;
+ struct cdrom_msf *msf=(struct cdrom_msf *) arg;
xtrace(IOCTL, "ioctl() PLAYMSF\n");
if ((stuffp->audiostatus == CDROM_AUDIO_PLAY)
&& (-1 == mcdx_hold(stuffp, 1))) return -EIO;
- if ((ans = verify_area(
- VERIFY_READ, (void*) arg, sizeof(struct cdrom_msf))))
- return ans;
-
- copy_from_user(&msf, (void*) arg, sizeof msf);
-
- msf.cdmsf_min0 = uint2bcd(msf.cdmsf_min0);
- msf.cdmsf_sec0 = uint2bcd(msf.cdmsf_sec0);
- msf.cdmsf_frame0 = uint2bcd(msf.cdmsf_frame0);
+ msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0);
+ msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0);
+ msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0);
+
+ msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1);
+ msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1);
+ msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1);
+
+ stuffp->stop.dt.minute = msf->cdmsf_min1;
+ stuffp->stop.dt.second = msf->cdmsf_sec1;
+ stuffp->stop.dt.frame = msf->cdmsf_frame1;
- msf.cdmsf_min1 = uint2bcd(msf.cdmsf_min1);
- msf.cdmsf_sec1 = uint2bcd(msf.cdmsf_sec1);
- msf.cdmsf_frame1 = uint2bcd(msf.cdmsf_frame1);
-
- stuffp->stop.dt.minute = msf.cdmsf_min1;
- stuffp->stop.dt.second = msf.cdmsf_sec1;
- stuffp->stop.dt.frame = msf.cdmsf_frame1;
-
- return mcdx_playmsf(stuffp, &msf);
+ return mcdx_playmsf(stuffp, msf);
}
case CDROMRESUME: {
@@ -372,103 +401,70 @@
}
case CDROMREADTOCENTRY: {
- struct cdrom_tocentry entry;
+ struct cdrom_tocentry *entry=(struct cdrom_tocentry *) arg;
struct s_subqcode *tp = NULL;
- int ans;
-
xtrace(IOCTL, "ioctl() READTOCENTRY\n");
if (-1 == mcdx_readtoc(stuffp)) return -1;
-
- if ((ans = verify_area(VERIFY_WRITE, (void *) arg, sizeof(entry)))) return ans;
- copy_from_user(&entry, (void *) arg, sizeof(entry));
-
- if (entry.cdte_track == CDROM_LEADOUT)
+ if (entry->cdte_track == CDROM_LEADOUT)
tp = &stuffp->toc[stuffp->di.n_last - stuffp->di.n_first + 1];
- else if (entry.cdte_track > stuffp->di.n_last
- || entry.cdte_track < stuffp->di.n_first) return -EINVAL;
- else tp = &stuffp->toc[entry.cdte_track - stuffp->di.n_first];
-
- if (NULL == tp) xwarn("FATAL.\n");
-
- entry.cdte_adr = tp->control;
- entry.cdte_ctrl = tp->control >> 4;
-
- if (entry.cdte_format == CDROM_MSF) {
- entry.cdte_addr.msf.minute = bcd2uint(tp->dt.minute);
- entry.cdte_addr.msf.second = bcd2uint(tp->dt.second);
- entry.cdte_addr.msf.frame = bcd2uint(tp->dt.frame);
- } else if (entry.cdte_format == CDROM_LBA)
- entry.cdte_addr.lba = msf2log(&tp->dt);
- else return -EINVAL;
-
- copy_to_user((void*) arg, &entry, sizeof(entry));
+ else if (entry->cdte_track > stuffp->di.n_last
+ || entry->cdte_track < stuffp->di.n_first) return -EINVAL;
+ else tp = &stuffp->toc[entry->cdte_track - stuffp->di.n_first];
+ if (NULL == tp)
+ return -EIO;
+ entry->cdte_adr = tp->control;
+ entry->cdte_ctrl = tp->control >> 4;
+ /* Always return stuff in MSF, and let the Uniform cdrom driver
+ worry about what the user actually wants */
+ entry->cdte_addr.msf.minute = bcd2uint(tp->dt.minute);
+ entry->cdte_addr.msf.second = bcd2uint(tp->dt.second);
+ entry->cdte_addr.msf.frame = bcd2uint(tp->dt.frame);
return 0;
}
case CDROMSUBCHNL: {
- int ans;
- struct cdrom_subchnl sub;
+ struct cdrom_subchnl *sub= (struct cdrom_subchnl *)arg;
struct s_subqcode q;
xtrace(IOCTL, "ioctl() SUBCHNL\n");
- if ((ans = verify_area(VERIFY_WRITE,
- (void*) arg, sizeof(sub)))) return ans;
-
- copy_from_user(&sub, (void*) arg, sizeof(sub));
-
- if (-1 == mcdx_requestsubqcode(stuffp, &q, 2)) return -EIO;
+ if (-1 == mcdx_requestsubqcode(stuffp, &q, 2))
+ return -EIO;
xtrace(SUBCHNL, "audiostatus: %x\n", stuffp->audiostatus);
- sub.cdsc_audiostatus = stuffp->audiostatus;
- sub.cdsc_adr = q.control;
- sub.cdsc_ctrl = q.control >> 4;
- sub.cdsc_trk = bcd2uint(q.tno);
- sub.cdsc_ind = bcd2uint(q.index);
+ sub->cdsc_audiostatus = stuffp->audiostatus;
+ sub->cdsc_adr = q.control;
+ sub->cdsc_ctrl = q.control >> 4;
+ sub->cdsc_trk = bcd2uint(q.tno);
+ sub->cdsc_ind = bcd2uint(q.index);
xtrace(SUBCHNL, "trk %d, ind %d\n",
- sub.cdsc_trk, sub.cdsc_ind);
-
- if (sub.cdsc_format == CDROM_LBA) {
- sub.cdsc_absaddr.lba = msf2log(&q.dt);
- sub.cdsc_reladdr.lba = msf2log(&q.tt);
- xtrace(SUBCHNL, "lba: abs %d, rel %d\n",
- sub.cdsc_absaddr.lba,
- sub.cdsc_reladdr.lba);
- } else if (sub.cdsc_format == CDROM_MSF) {
- sub.cdsc_absaddr.msf.minute = bcd2uint(q.dt.minute);
- sub.cdsc_absaddr.msf.second = bcd2uint(q.dt.second);
- sub.cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
- sub.cdsc_reladdr.msf.minute = bcd2uint(q.tt.minute);
- sub.cdsc_reladdr.msf.second = bcd2uint(q.tt.second);
- sub.cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
- xtrace(SUBCHNL,
- "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
- sub.cdsc_absaddr.msf.minute,
- sub.cdsc_absaddr.msf.second,
- sub.cdsc_absaddr.msf.frame,
- sub.cdsc_reladdr.msf.minute,
- sub.cdsc_reladdr.msf.second,
- sub.cdsc_reladdr.msf.frame);
- } else return -EINVAL;
-
- copy_to_user((void*) arg, &sub, sizeof(sub));
+ sub->cdsc_trk, sub->cdsc_ind);
+ /* Always return stuff in MSF, and let the Uniform cdrom driver
+ worry about what the user actually wants */
+ sub->cdsc_absaddr.msf.minute = bcd2uint(q.dt.minute);
+ sub->cdsc_absaddr.msf.second = bcd2uint(q.dt.second);
+ sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
+ sub->cdsc_reladdr.msf.minute = bcd2uint(q.tt.minute);
+ sub->cdsc_reladdr.msf.second = bcd2uint(q.tt.second);
+ sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
+ xtrace(SUBCHNL,
+ "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
+ sub->cdsc_absaddr.msf.minute, sub->cdsc_absaddr.msf.second,
+ sub->cdsc_absaddr.msf.frame, sub->cdsc_reladdr.msf.minute,
+ sub->cdsc_reladdr.msf.second, sub->cdsc_reladdr.msf.frame);
return 0;
}
case CDROMREADTOCHDR: {
- struct cdrom_tochdr toc;
- int ans;
+ struct cdrom_tochdr *toc=(struct cdrom_tochdr *) arg;
xtrace(IOCTL, "ioctl() READTOCHDR\n");
- if ((ans = verify_area(VERIFY_WRITE, (void*) arg, sizeof toc)))
- return ans;
- toc.cdth_trk0 = stuffp->di.n_first;
- toc.cdth_trk1 = stuffp->di.n_last;
- copy_to_user((void*) arg, &toc, sizeof toc);
+ toc->cdth_trk0 = stuffp->di.n_first;
+ toc->cdth_trk1 = stuffp->di.n_last;
xtrace(TOCHDR, "ioctl() track0 = %d, track1 = %d\n",
stuffp->di.n_first, stuffp->di.n_last);
return 0;
@@ -485,78 +481,41 @@
}
case CDROMMULTISESSION: {
- int ans;
- struct cdrom_multisession ms;
+ struct cdrom_multisession *ms=(struct cdrom_multisession *) arg;
xtrace(IOCTL, "ioctl() MULTISESSION\n");
- if (0 != (ans = verify_area(VERIFY_WRITE, (void*) arg,
- sizeof(struct cdrom_multisession))))
- return ans;
-
- copy_from_user(&ms, (void*) arg, sizeof(struct cdrom_multisession));
- if (ms.addr_format == CDROM_MSF) {
- ms.addr.msf.minute = bcd2uint(stuffp->multi.msf_last.minute);
- ms.addr.msf.second = bcd2uint(stuffp->multi.msf_last.second);
- ms.addr.msf.frame = bcd2uint(stuffp->multi.msf_last.frame);
- } else if (ms.addr_format == CDROM_LBA)
- ms.addr.lba = msf2log(&stuffp->multi.msf_last);
- else
- return -EINVAL;
- ms.xa_flag = !!stuffp->multi.multi;
-
- copy_to_user((void*) arg, &ms, sizeof(struct cdrom_multisession));
- if (ms.addr_format == CDROM_MSF) {
- xtrace(MS,
- "ioctl() (%d, %02x:%02x.%02x [%02x:%02x.%02x])\n",
- ms.xa_flag,
- ms.addr.msf.minute,
- ms.addr.msf.second,
- ms.addr.msf.frame,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
- } else {
- xtrace(MS,
- "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
- ms.xa_flag,
- ms.addr.lba,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
- }
+ /* Always return stuff in LBA, and let the Uniform cdrom driver
+ worry about what the user actually wants */
+ ms->addr.lba = msf2log(&stuffp->multi.msf_last);
+ ms->xa_flag = !!stuffp->multi.multi;
+ xtrace(MS, "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
+ ms->xa_flag, ms->addr.lba, stuffp->multi.msf_last.minute,
+ stuffp->multi.msf_last.second,stuffp->multi.msf_last.frame);
+
return 0;
}
case CDROMEJECT: {
xtrace(IOCTL, "ioctl() EJECT\n");
if (stuffp->users > 1) return -EBUSY;
- if (-1 == mcdx_eject(stuffp, 1)) return -EIO;
- return 0;
+ return(mcdx_tray_move(cdi, 1));
}
- case CDROMEJECT_SW: {
- stuffp->eject_sw = arg;
- return 0;
+ case CDROMCLOSETRAY: {
+ xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n");
+ return(mcdx_tray_move(cdi, 0));
}
case CDROMVOLCTRL: {
- int ans;
- struct cdrom_volctrl volctrl;
-
+ struct cdrom_volctrl *volctrl=(struct cdrom_volctrl *)arg;
xtrace(IOCTL, "ioctl() VOLCTRL\n");
- if ((ans = verify_area(
- VERIFY_READ,
- (void*) arg,
- sizeof(volctrl))))
- return ans;
- copy_from_user(&volctrl, (char *) arg, sizeof(volctrl));
#if 0 /* not tested! */
/* adjust for the weirdness of workman (md) */
/* can't test it (hs) */
volctrl.channel2 = volctrl.channel1;
volctrl.channel1 = volctrl.channel3 = 0x00;
#endif
- return mcdx_setattentuator(stuffp, &volctrl, 2);
+ return mcdx_setattentuator(stuffp, volctrl, 2);
}
default:
@@ -645,19 +604,12 @@
goto again;
}
-static int
-mcdx_open(struct inode *ip, struct file *fp)
-/* actions done on open:
- * 1) get the drives status
- * 2) set the stuffp.readcmd if a CD is in.
- * (return no error if no CD is found, since ioctl()
- * needs an opened device */
+static int
+mcdx_open(struct cdrom_device_info * cdi, int purpose)
{
struct s_drive_stuff *stuffp;
-
xtrace(OPENCLOSE, "open()\n");
-
- stuffp = mcdx_stuffp[MINOR(ip->i_rdev)];
+ stuffp = mcdx_stuffp[MINOR(cdi->dev)];
if (!stuffp->present) return -ENXIO;
/* Make the modules looking used ... (thanx bjorn).
@@ -665,248 +617,154 @@
* on error return */
MOD_INC_USE_COUNT;
-#if 0
- /* We don't allow multiple users of a drive. In case of data CDs
- * they'll be used by mounting, which ensures anyway exclusive
- * usage. In case of audio CDs it's meaningless to try playing to
- * different tracks at once! (md)
- * - Hey, what about cat /dev/cdrom? Why shouldn't it called by
- * more then one process at any time? (hs) */
- if (stuffp->users) {
- MOD_DEC_USE_COUNT;
- return -EBUSY;
- }
-#endif
-
/* this is only done to test if the drive talks with us */
if (-1 == mcdx_getstatus(stuffp, 1)) {
MOD_DEC_USE_COUNT;
return -EIO;
}
- /* close the door,
- * This should be explained ...
- * - If the door is open and its last close is too recent the
- * autoclose wouldn't probably be what we want.
- * - If we didn't try to close the door yet, close it and go on.
- * - If we autoclosed the door and couldn't succeed in find a valid
- * CD we shouldn't try autoclose any longer (until a valid CD is
- * in.) */
-
- if (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_DOOR) {
- if (jiffies - stuffp->ejected < ACLOSE_INHIBIT) {
- MOD_DEC_USE_COUNT;
- return -EIO;
- }
- if (stuffp->autoclose) mcdx_closedoor(stuffp, 1);
- else {
- MOD_DEC_USE_COUNT;
- return -EIO;
- }
- }
-
- /* if the media changed we will have to do a little more */
- if (stuffp->xxx) {
-
- xtrace(OPENCLOSE, "open() media changed\n");
- /* but wait - the time of media change will be set at the
- * very last of this block - it seems, some of the following
- * talk() will detect a media change ... (I think, config()
- * is the reason. */
+ if (stuffp->xxx) {
+ xtrace(OPENCLOSE, "open() media changed\n");
stuffp->audiostatus = CDROM_AUDIO_INVALID;
- stuffp->readcmd = 0;
-
- /* get the multisession information */
- xtrace(OPENCLOSE, "open() Request multisession info\n");
- if (-1 == mcdx_requestmultidiskinfo(
- stuffp, &stuffp->multi, 6)) {
- xinfo("No multidiskinfo\n");
- stuffp->autoclose = 0;
- /*
- MOD_DEC_USE_COUNT;
- stuffp->xxx = 0;
- return -EIO;
- */
- } else {
- /* we succeeded, so on next open(2) we could try auto close
- * again */
- stuffp->autoclose = 1;
-
-#if !MCDX_QUIET
- if (stuffp->multi.multi > 2)
- xinfo("open() unknown multisession value (%d)\n",
- stuffp->multi.multi);
-#endif
-
- /* multisession ? */
- if (!stuffp->multi.multi)
- stuffp->multi.msf_last.second = 2;
-
- xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",
- stuffp->multi.multi,
- stuffp->multi.msf_last.minute,
- stuffp->multi.msf_last.second,
- stuffp->multi.msf_last.frame);
-
- { ; } /* got multisession information */
-
- /* request the disks table of contents (aka diskinfo) */
- if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
-
- stuffp->lastsector = -1;
-
+ stuffp->readcmd = 0;
+ xtrace(OPENCLOSE, "open() Request multisession info\n");
+ if (-1 == mcdx_requestmultidiskinfo( stuffp, &stuffp->multi, 6))
+ xinfo("No multidiskinfo\n");
} else {
+ /* multisession ? */
+ if (!stuffp->multi.multi)
+ stuffp->multi.msf_last.second = 2;
+
+ xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",
+ stuffp->multi.multi,
+ stuffp->multi.msf_last.minute,
+ stuffp->multi.msf_last.second,
+ stuffp->multi.msf_last.frame);
+
+ { ; } /* got multisession information */
+ /* request the disks table of contents (aka diskinfo) */
+ if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
+
+ stuffp->lastsector = -1;
+
+ } else {
+
+ stuffp->lastsector = (CD_FRAMESIZE / 512)
+ * msf2log(&stuffp->di.msf_leadout) - 1;
+
+ xtrace(OPENCLOSE, "open() start %d (%02x:%02x.%02x) %d\n",
+ stuffp->di.n_first,
+ stuffp->di.msf_first.minute,
+ stuffp->di.msf_first.second,
+ stuffp->di.msf_first.frame,
+ msf2log(&stuffp->di.msf_first));
+ xtrace(OPENCLOSE, "open() last %d (%02x:%02x.%02x) %d\n",
+ stuffp->di.n_last,
+ stuffp->di.msf_leadout.minute,
+ stuffp->di.msf_leadout.second,
+ stuffp->di.msf_leadout.frame,
+ msf2log(&stuffp->di.msf_leadout));
+ }
+
+ if (stuffp->toc) {
+ xtrace(MALLOC, "open() free old toc @ %p\n", stuffp->toc);
+ kfree(stuffp->toc);
- stuffp->lastsector = (CD_FRAMESIZE / 512)
- * msf2log(&stuffp->di.msf_leadout) - 1;
-
- xtrace(OPENCLOSE, "open() start %d (%02x:%02x.%02x) %d\n",
- stuffp->di.n_first,
- stuffp->di.msf_first.minute,
- stuffp->di.msf_first.second,
- stuffp->di.msf_first.frame,
- msf2log(&stuffp->di.msf_first));
- xtrace(OPENCLOSE, "open() last %d (%02x:%02x.%02x) %d\n",
- stuffp->di.n_last,
- stuffp->di.msf_leadout.minute,
- stuffp->di.msf_leadout.second,
- stuffp->di.msf_leadout.frame,
- msf2log(&stuffp->di.msf_leadout));
- }
-
- if (stuffp->toc) {
- xtrace(MALLOC, "open() free old toc @ %p\n", stuffp->toc);
- kfree(stuffp->toc);
-
- stuffp->toc = NULL;
- }
+ stuffp->toc = NULL;
+ }
- xtrace(OPENCLOSE, "open() init irq generation\n");
- if (-1 == mcdx_config(stuffp, 1)) {
- MOD_DEC_USE_COUNT;
- return -EIO;
- }
+ xtrace(OPENCLOSE, "open() init irq generation\n");
+ if (-1 == mcdx_config(stuffp, 1)) {
+ MOD_DEC_USE_COUNT;
+ return -EIO;
+ }
#if FALLBACK
- /* Set the read speed */
- xwarn("AAA %x AAA\n", stuffp->readcmd);
- if (stuffp->readerrs) stuffp->readcmd = READ1X;
- else stuffp->readcmd =
- stuffp->present | SINGLE ? READ1X : READ2X;
- xwarn("XXX %x XXX\n", stuffp->readcmd);
+ /* Set the read speed */
+ xwarn("AAA %x AAA\n", stuffp->readcmd);
+ if (stuffp->readerrs) stuffp->readcmd = READ1X;
+ else stuffp->readcmd =
+ stuffp->present | SINGLE ? READ1X : READ2X;
+ xwarn("XXX %x XXX\n", stuffp->readcmd);
#else
- stuffp->readcmd = stuffp->present | SINGLE ? READ1X : READ2X;
+ stuffp->readcmd = stuffp->present | SINGLE ? READ1X : READ2X;
#endif
- /* try to get the first sector, iff any ... */
- if (stuffp->lastsector >= 0) {
- char buf[512];
- int ans;
- int tries;
-
- stuffp->xa = 0;
- stuffp->audio = 0;
-
- for (tries = 6; tries; tries--) {
-
- stuffp->introk = 1;
-
- xtrace(OPENCLOSE, "open() try as %s\n",
- stuffp->xa ? "XA" : "normal");
-
- /* set data mode */
- if (-1 == (ans = mcdx_setdatamode(stuffp,
- stuffp->xa ? MODE2 : MODE1, 1))) {
- /* MOD_DEC_USE_COUNT, return -EIO; */
- stuffp->xa = 0;
- break;
- }
+ /* try to get the first sector, iff any ... */
+ if (stuffp->lastsector >= 0) {
+ char buf[512];
+ int ans;
+ int tries;
- if ((stuffp->audio = e_audio(ans))) break;
+ stuffp->xa = 0;
+ stuffp->audio = 0;
- while (0 == (ans = mcdx_transfer(stuffp, buf, 0, 1)))
- ;
+ for (tries = 6; tries; tries--) {
- if (ans == 1) break;
- stuffp->xa = !stuffp->xa;
- }
- /* if (!tries) MOD_DEC_USE_COUNT, return -EIO; */
- }
+ stuffp->introk = 1;
- /* xa disks will be read in raw mode, others not */
- if (-1 == mcdx_setdrivemode(stuffp,
- stuffp->xa ? RAW : COOKED, 1)) {
- MOD_DEC_USE_COUNT;
- return -EIO;
- }
+ xtrace(OPENCLOSE, "open() try as %s\n",
+ stuffp->xa ? "XA" : "normal");
+ /* set data mode */
+ if (-1 == (ans = mcdx_setdatamode(stuffp,
+ stuffp->xa ? MODE2 : MODE1, 1))) {
+ /* MOD_DEC_USE_COUNT, return -EIO; */
+ stuffp->xa = 0;
+ break;
+ }
- if (stuffp->audio) {
- xinfo("open() audio disk found\n");
- } else if (stuffp->lastsector >= 0) {
- xinfo("open() %s%s disk found\n",
- stuffp->xa ? "XA / " : "",
- stuffp->multi.multi ? "Multi Session" : "Single Session");
- }
+ if ((stuffp->audio = e_audio(ans))) break;
- /* stuffp->xxx = 0; */
- }
-
- /* lock the door if not already done */
- if (0 == stuffp->users && (-1 == mcdx_lockdoor(stuffp, 1, 1))) {
- MOD_DEC_USE_COUNT;
- return -EIO;
- }
- }
+ while (0 == (ans = mcdx_transfer(stuffp, buf, 0, 1)))
+ ;
+ if (ans == 1) break;
+ stuffp->xa = !stuffp->xa;
+ }
+ }
+ /* xa disks will be read in raw mode, others not */
+ if (-1 == mcdx_setdrivemode(stuffp,
+ stuffp->xa ? RAW : COOKED, 1)) {
+ MOD_DEC_USE_COUNT;
+ return -EIO;
+ }
+ if (stuffp->audio) {
+ xinfo("open() audio disk found\n");
+ } else if (stuffp->lastsector >= 0) {
+ xinfo("open() %s%s disk found\n",
+ stuffp->xa ? "XA / " : "",
+ stuffp->multi.multi ? "Multi Session" : "Single Session");
+ }
+ }
stuffp->xxx = 0;
stuffp->users++;
return 0;
-
}
-static int
-mcdx_close(struct inode *ip, struct file *fp)
+static void mcdx_close(struct cdrom_device_info * cdi)
{
struct s_drive_stuff *stuffp;
xtrace(OPENCLOSE, "close()\n");
- stuffp = mcdx_stuffp[MINOR(ip->i_rdev)];
-
- if (0 == --stuffp->users) {
- sync_dev(ip->i_rdev); /* needed for r/o device? */
-
- /* invalidate_inodes(ip->i_rdev); */
- invalidate_buffers(ip->i_rdev);
-
-
-#if !MCDX_QUIET
- if (-1 == mcdx_lockdoor(stuffp, 0, 3))
- xinfo("close() Cannot unlock the door\n");
-#else
- mcdx_lockdoor(stuffp, 0, 3);
-#endif
-
- /* eject if wished */
- if (stuffp->eject_sw) mcdx_eject(stuffp, 1);
+ stuffp = mcdx_stuffp[MINOR(cdi->dev)];
- }
+ --stuffp->users;
MOD_DEC_USE_COUNT;
- return 0;
}
-int check_mcdx_media_change(kdev_t full_dev)
+static int mcdx_media_changed(struct cdrom_device_info * cdi, int disc_nr)
/* Return: 1 if media changed since last call to this function
0 otherwise */
{
struct s_drive_stuff *stuffp;
- xinfo("check_mcdx_media_change called for device %s\n",
- kdevname(full_dev));
+ xinfo("mcdx_media_changed called for device %s\n",
+ kdevname(cdi->dev));
- stuffp = mcdx_stuffp[MINOR(full_dev)];
+ stuffp = mcdx_stuffp[MINOR(cdi->dev)];
mcdx_getstatus(stuffp, 1);
if (stuffp->yyy == 0) return 0;
@@ -1140,6 +998,10 @@
for (i = 0; i < MCDX_NDRIVES; i++) {
struct s_drive_stuff *stuffp;
+ if (unregister_cdrom(&mcdx_info)) {
+ printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
+ return;
+ }
stuffp = mcdx_stuffp[i];
if (!stuffp) continue;
release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE);
@@ -1153,7 +1015,7 @@
kfree(stuffp);
}
- if (unregister_blkdev(MAJOR_NR, DEVICE_NAME) != 0) {
+ if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
xwarn("cleanup() unregister_blkdev() failed\n");
}
#if !MCDX_QUIET
@@ -1168,7 +1030,7 @@
__initfunc(int mcdx_init(void))
{
int drive;
-
+ char msg[80];
#ifdef MODULE
xwarn("Version 2.14(hs) for " UTS_RELEASE "\n");
#else
@@ -1204,7 +1066,6 @@
/* set default values */
memset(stuffp, 0, sizeof(*stuffp));
- stuffp->autoclose = 1; /* close the door on open(2) */
stuffp->present = 0; /* this should be 0 already */
stuffp->toc = NULL; /* this should be NULL already */
@@ -1274,7 +1135,7 @@
}
xtrace(INIT, "init() register blkdev\n");
- if (register_blkdev(MAJOR_NR, DEVICE_NAME, &mcdx_fops) != 0) {
+ if (register_blkdev(MAJOR_NR, "mcdx", &cdrom_fops) != 0) {
xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n",
MCDX,
stuffp->wreg_data, stuffp->irq, MAJOR_NR);
@@ -1289,7 +1150,7 @@
xtrace(INIT, "init() subscribe irq and i/o\n");
mcdx_irq_map[stuffp->irq] = stuffp;
- if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, DEVICE_NAME, NULL)) {
+ if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, "mcdx", NULL)) {
xwarn("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n",
MCDX,
stuffp->wreg_data, stuffp->irq, stuffp->irq);
@@ -1299,7 +1160,7 @@
}
request_region((unsigned int) stuffp->wreg_data,
MCDX_IO_SIZE,
- DEVICE_NAME);
+ "mcdx");
xtrace(INIT, "init() get garbage\n");
{
@@ -1318,15 +1179,23 @@
stuffp->minor = drive;
- xwarn("(%s) installed at 0x%3p, irq %d."
- " (Firmware version %c %x)\n",
- DEVICE_NAME,
+ sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d."
+ " (Firmware version %c %x)\n",
stuffp->wreg_data, stuffp->irq, version.code,
version.ver);
mcdx_stuffp[drive] = stuffp;
xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
+ if (register_cdrom(&mcdx_info) != 0) {
+ printk("Cannot register Mitsumi CD-ROM!\n");
+ release_region((unsigned long) stuffp->wreg_data, MCDX_IO_SIZE);
+ free_irq(stuffp->irq, NULL);
+ kfree(stuffp);
+ if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
+ xwarn("cleanup() unregister_blkdev() failed\n");
+ return -EIO;
+ }
+ printk(msg);
}
-
return 0;
}
@@ -1539,7 +1408,7 @@
static void log2msf(unsigned int l, struct cdrom_msf0* pmsf)
{
- l += CD_BLOCK_OFFSET;
+ l += CD_MSF_OFFSET;
pmsf->minute = uint2bcd(l / 4500), l %= 4500;
pmsf->second = uint2bcd(l / 75);
pmsf->frame = uint2bcd(l % 75);
@@ -1550,7 +1419,7 @@
return bcd2uint(pmsf->frame)
+ bcd2uint(pmsf->second) * 75
+ bcd2uint(pmsf->minute) * 4500
- - CD_BLOCK_OFFSET;
+ - CD_MSF_OFFSET;
}
int mcdx_readtoc(struct s_drive_stuff* stuffp)
@@ -1712,12 +1581,20 @@
/* Drive functions ************************************************/
static int
-mcdx_closedoor(struct s_drive_stuff *stuffp, int tries)
+mcdx_tray_move(struct cdrom_device_info * cdi, int position)
{
- if (stuffp->present & DOOR)
- return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, tries);
- else
- return 0;
+ struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
+
+ if (!stuffp->present)
+ return -ENXIO;
+ if (!(stuffp->present & DOOR))
+ return -ENOSYS;
+
+ if (position) /* 1: eject */
+ return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3);
+ else /* 0: close */
+ return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3);
+ return 1;
}
static int
@@ -1729,15 +1606,6 @@
{ return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries); }
static int
-mcdx_eject(struct s_drive_stuff *stuffp, int tries)
-{
- if (stuffp->present & DOOR) {
- stuffp->ejected = jiffies;
- return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, tries);
- } else return 0;
-}
-
-static int
mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
struct s_subqcode *sub,
int tries)
@@ -1886,13 +1754,16 @@
} else return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);
}
-static int
-mcdx_lockdoor(struct s_drive_stuff *stuffp, int lock, int tries)
+static int mcdx_lockdoor(struct cdrom_device_info * cdi, int lock)
{
+ struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
char cmd[2] = { 0xfe };
+
+ if (!(stuffp->present & DOOR))
+ return -ENOSYS;
if (stuffp->present & DOOR) {
cmd[1] = lock ? 0x01 : 0x00;
- return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, tries);
+ return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);
} else return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov