File: /usr/src/linux/drivers/cdrom/mcdx.c

1     /*
2      * The Mitsumi CDROM interface
3      * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
4      * VERSION: 2.14(hs)
5      *
6      * ... anyway, I'm back again, thanks to Marcin, he adopted
7      * large portions of my code (at least the parts containing
8      * my main thoughts ...)
9      *
10      ****************** H E L P *********************************
11      * If you ever plan to update your CD ROM drive and perhaps
12      * want to sell or simply give away your Mitsumi FX-001[DS]
13      * -- Please --
14      * mail me (heiko@lotte.sax.de).  When my last drive goes
15      * ballistic no more driver support will be available from me!
16      *************************************************************
17      *
18      * This program is free software; you can redistribute it and/or modify
19      * it under the terms of the GNU General Public License as published by
20      * the Free Software Foundation; either version 2, or (at your option)
21      * any later version.
22      *
23      * This program is distributed in the hope that it will be useful,
24      * but WITHOUT ANY WARRANTY; without even the implied warranty of
25      * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26      * GNU General Public License for more details.
27      *
28      * You should have received a copy of the GNU General Public License
29      * along with this program; see the file COPYING.  If not, write to
30      * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
31      *
32      * Thanks to
33      *  The Linux Community at all and ...
34      *  Martin Harriss (he wrote the first Mitsumi Driver)
35      *  Eberhard Moenkeberg (he gave me much support and the initial kick)
36      *  Bernd Huebner, Ruediger Helsch (Unifix-Software GmbH, they
37      *      improved the original driver)
38      *  Jon Tombs, Bjorn Ekwall (module support)
39      *  Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
40      *  Gerd Knorr (he lent me his PhotoCD)
41      *  Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
42      *  Andreas Kies (testing the mysterious hang-ups)
43      *  Heiko Eissfeldt (VERIFY_READ/WRITE)
44      *  Marcin Dalecki (improved performance, shortened code)
45      *  ... somebody forgotten?
46      *
47      *  9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
48      *	               Removed init_module & cleanup_module in favor of 
49      *		       module_init & module_exit.
50      *		       Torben Mathiasen <tmm@image.dk>
51      */
52     
53     
54     #if RCS
55     static const char *mcdx_c_version
56         = "$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $";
57     #endif
58     
59     #include <linux/version.h>
60     #include <linux/module.h>
61     
62     #include <linux/errno.h>
63     #include <linux/sched.h>
64     #include <linux/fs.h>
65     #include <linux/kernel.h>
66     #include <linux/cdrom.h>
67     #include <linux/ioport.h>
68     #include <linux/mm.h>
69     #include <linux/slab.h>
70     #include <linux/init.h>
71     #include <asm/io.h>
72     #include <asm/uaccess.h>
73     
74     #include <linux/major.h>
75     #define MAJOR_NR MITSUMI_X_CDROM_MAJOR
76     #include <linux/blk.h>
77     #include <linux/devfs_fs_kernel.h>
78     
79     /* for compatible parameter passing with "insmod" */
80     #define	mcdx_drive_map mcdx
81     #include "mcdx.h"
82     
83     #if BITS_PER_LONG != 32
84     #  error FIXME: this driver only works on 32-bit platforms
85     #endif
86     
87     #ifndef HZ
88     #error HZ not defined
89     #endif
90     
91     #define xwarn(fmt, args...) printk(KERN_WARNING MCDX " " fmt, ## args)
92     
93     #if !MCDX_QUIET
94     #define xinfo(fmt, args...) printk(KERN_INFO MCDX " " fmt, ## args)
95     #else
96     #define xinfo(fmt, args...) { ; }
97     #endif
98     
99     #if MCDX_DEBUG
100     #define xtrace(lvl, fmt, args...) \
101     		{ if (lvl > 0) \
102     			{ printk(KERN_DEBUG MCDX ":: " fmt, ## args); } }
103     #define xdebug(fmt, args...) printk(KERN_DEBUG MCDX ":: " fmt, ## args)
104     #else
105     #define xtrace(lvl, fmt, args...) { ; }
106     #define xdebug(fmt, args...) { ; }
107     #endif
108     
109     /* CONSTANTS *******************************************************/
110     
111     /* Following are the number of sectors we _request_ from the drive
112        every time an access outside the already requested range is done.
113        The _direct_ size is the number of sectors we're allowed to skip
114        directly (performing a read instead of requesting the new sector
115        needed */
116     const int REQUEST_SIZE = 800;	/* should be less then 255 * 4 */
117     const int DIRECT_SIZE = 400;	/* should be less then REQUEST_SIZE */
118     
119     enum drivemodes { TOC, DATA, RAW, COOKED };
120     enum datamodes { MODE0, MODE1, MODE2 };
121     enum resetmodes { SOFT, HARD };
122     
123     const int SINGLE = 0x01;	/* single speed drive (FX001S, LU) */
124     const int DOUBLE = 0x02;	/* double speed drive (FX001D, ..? */
125     const int DOOR = 0x04;		/* door locking capability */
126     const int MULTI = 0x08;		/* multi session capability */
127     
128     const unsigned char READ1X = 0xc0;
129     const unsigned char READ2X = 0xc1;
130     
131     
132     /* DECLARATIONS ****************************************************/
133     struct s_subqcode {
134     	unsigned char control;
135     	unsigned char tno;
136     	unsigned char index;
137     	struct cdrom_msf0 tt;
138     	struct cdrom_msf0 dt;
139     };
140     
141     struct s_diskinfo {
142     	unsigned int n_first;
143     	unsigned int n_last;
144     	struct cdrom_msf0 msf_leadout;
145     	struct cdrom_msf0 msf_first;
146     };
147     
148     struct s_multi {
149     	unsigned char multi;
150     	struct cdrom_msf0 msf_last;
151     };
152     
153     struct s_version {
154     	unsigned char code;
155     	unsigned char ver;
156     };
157     
158     /* Per drive/controller stuff **************************************/
159     
160     struct s_drive_stuff {
161     	/* waitqueues */
162     	wait_queue_head_t busyq;
163     	wait_queue_head_t lockq;
164     	wait_queue_head_t sleepq;
165     
166     	/* flags */
167     	volatile int introk;	/* status of last irq operation */
168     	volatile int busy;	/* drive performs an operation */
169     	volatile int lock;	/* exclusive usage */
170     
171     	/* cd infos */
172     	struct s_diskinfo di;
173     	struct s_multi multi;
174     	struct s_subqcode *toc;	/* first entry of the toc array */
175     	struct s_subqcode start;
176     	struct s_subqcode stop;
177     	int xa;			/* 1 if xa disk */
178     	int audio;		/* 1 if audio disk */
179     	int audiostatus;
180     
181     	/* `buffer' control */
182     	volatile int valid;	/* pending, ..., values are valid */
183     	volatile int pending;	/* next sector to be read */
184     	volatile int low_border;	/* first sector not to be skipped direct */
185     	volatile int high_border;	/* first sector `out of area' */
186     #ifdef AK2
187     	volatile int int_err;
188     #endif				/* AK2 */
189     
190     	/* adds and odds */
191     	void *wreg_data;	/* w data */
192     	void *wreg_reset;	/* w hardware reset */
193     	void *wreg_hcon;	/* w hardware conf */
194     	void *wreg_chn;		/* w channel */
195     	void *rreg_data;	/* r data */
196     	void *rreg_status;	/* r status */
197     
198     	int irq;		/* irq used by this drive */
199     	int minor;		/* minor number of this drive */
200     	int present;		/* drive present and its capabilities */
201     	unsigned char readcmd;	/* read cmd depends on single/double speed */
202     	unsigned char playcmd;	/* play should always be single speed */
203     	unsigned int xxx;	/* set if changed, reset while open */
204     	unsigned int yyy;	/* set if changed, reset by media_changed */
205     	int users;		/* keeps track of open/close */
206     	int lastsector;		/* last block accessible */
207     	int status;		/* last operation's error / status */
208     	int readerrs;		/* # of blocks read w/o error */
209     };
210     
211     
212     /* Prototypes ******************************************************/
213     
214     /*	The following prototypes are already declared elsewhere.  They are
215      	repeated here to show what's going on.  And to sense, if they're
216     	changed elsewhere. */
217     
218     /* declared in blk.h */
219     int mcdx_init(void);
220     void do_mcdx_request(request_queue_t * q);
221     
222     
223     /*	Indirect exported functions. These functions are exported by their
224     	addresses, such as mcdx_open and mcdx_close in the
225     	structure mcdx_dops. */
226     
227     /* ???  exported by the mcdx_sigaction struct */
228     static void mcdx_intr(int, void *, struct pt_regs *);
229     
230     /* exported by file_ops */
231     static int mcdx_open(struct cdrom_device_info *cdi, int purpose);
232     static void mcdx_close(struct cdrom_device_info *cdi);
233     static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr);
234     static int mcdx_tray_move(struct cdrom_device_info *cdi, int position);
235     static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock);
236     static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
237     			    unsigned int cmd, void *arg);
238     
239     /* misc internal support functions */
240     static void log2msf(unsigned int, struct cdrom_msf0 *);
241     static unsigned int msf2log(const struct cdrom_msf0 *);
242     static unsigned int uint2bcd(unsigned int);
243     static unsigned int bcd2uint(unsigned char);
244     static char *port(int *);
245     static int irq(int *);
246     static void mcdx_delay(struct s_drive_stuff *, long jifs);
247     static int mcdx_transfer(struct s_drive_stuff *, char *buf, int sector,
248     			 int nr_sectors);
249     static int mcdx_xfer(struct s_drive_stuff *, char *buf, int sector,
250     		     int nr_sectors);
251     
252     static int mcdx_config(struct s_drive_stuff *, int);
253     static int mcdx_requestversion(struct s_drive_stuff *, struct s_version *,
254     			       int);
255     static int mcdx_stop(struct s_drive_stuff *, int);
256     static int mcdx_hold(struct s_drive_stuff *, int);
257     static int mcdx_reset(struct s_drive_stuff *, enum resetmodes, int);
258     static int mcdx_setdrivemode(struct s_drive_stuff *, enum drivemodes, int);
259     static int mcdx_setdatamode(struct s_drive_stuff *, enum datamodes, int);
260     static int mcdx_requestsubqcode(struct s_drive_stuff *,
261     				struct s_subqcode *, int);
262     static int mcdx_requestmultidiskinfo(struct s_drive_stuff *,
263     				     struct s_multi *, int);
264     static int mcdx_requesttocdata(struct s_drive_stuff *, struct s_diskinfo *,
265     			       int);
266     static int mcdx_getstatus(struct s_drive_stuff *, int);
267     static int mcdx_getval(struct s_drive_stuff *, int to, int delay, char *);
268     static int mcdx_talk(struct s_drive_stuff *,
269     		     const unsigned char *cmd, size_t,
270     		     void *buffer, size_t size, unsigned int timeout, int);
271     static int mcdx_readtoc(struct s_drive_stuff *);
272     static int mcdx_playtrk(struct s_drive_stuff *, const struct cdrom_ti *);
273     static int mcdx_playmsf(struct s_drive_stuff *, const struct cdrom_msf *);
274     static int mcdx_setattentuator(struct s_drive_stuff *,
275     			       struct cdrom_volctrl *, int);
276     
277     /* static variables ************************************************/
278     
279     static int mcdx_blocksizes[MCDX_NDRIVES];
280     static int mcdx_drive_map[][2] = MCDX_DRIVEMAP;
281     static struct s_drive_stuff *mcdx_stuffp[MCDX_NDRIVES];
282     static struct s_drive_stuff *mcdx_irq_map[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
283     	0, 0, 0, 0, 0, 0, 0, 0
284     };
285     MODULE_PARM(mcdx, "1-4i");
286     
287     static struct cdrom_device_ops mcdx_dops = {
288     	open:mcdx_open,
289     	release:mcdx_close,
290     	media_changed:mcdx_media_changed,
291     	tray_move:mcdx_tray_move,
292     	lock_door:mcdx_lockdoor,
293     	audio_ioctl:mcdx_audio_ioctl,
294     	capability:CDC_OPEN_TRAY | CDC_LOCK | CDC_MEDIA_CHANGED |
295     	    CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
296     };
297     
298     static struct cdrom_device_info mcdx_info = {
299     	ops:&mcdx_dops,
300     	speed:2,
301     	capacity:1,
302     	name:"mcdx",
303     };
304     
305     
306     /* KERNEL INTERFACE FUNCTIONS **************************************/
307     
308     
309     static int mcdx_audio_ioctl(struct cdrom_device_info *cdi,
310     			    unsigned int cmd, void *arg)
311     {
312     	struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
313     
314     	if (!stuffp->present)
315     		return -ENXIO;
316     
317     	if (stuffp->xxx) {
318     		if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
319     			stuffp->lastsector = -1;
320     		} else {
321     			stuffp->lastsector = (CD_FRAMESIZE / 512)
322     			    * msf2log(&stuffp->di.msf_leadout) - 1;
323     		}
324     
325     		if (stuffp->toc) {
326     			kfree(stuffp->toc);
327     			stuffp->toc = NULL;
328     			if (-1 == mcdx_readtoc(stuffp))
329     				return -1;
330     		}
331     
332     		stuffp->xxx = 0;
333     	}
334     
335     	switch (cmd) {
336     	case CDROMSTART:{
337     			xtrace(IOCTL, "ioctl() START\n");
338     			/* Spin up the drive.  Don't think we can do this.
339     			   * For now, ignore it.
340     			 */
341     			return 0;
342     		}
343     
344     	case CDROMSTOP:{
345     			xtrace(IOCTL, "ioctl() STOP\n");
346     			stuffp->audiostatus = CDROM_AUDIO_INVALID;
347     			if (-1 == mcdx_stop(stuffp, 1))
348     				return -EIO;
349     			return 0;
350     		}
351     
352     	case CDROMPLAYTRKIND:{
353     			struct cdrom_ti *ti = (struct cdrom_ti *) arg;
354     
355     			xtrace(IOCTL, "ioctl() PLAYTRKIND\n");
356     			if ((ti->cdti_trk0 < stuffp->di.n_first)
357     			    || (ti->cdti_trk0 > stuffp->di.n_last)
358     			    || (ti->cdti_trk1 < stuffp->di.n_first))
359     				return -EINVAL;
360     			if (ti->cdti_trk1 > stuffp->di.n_last)
361     				ti->cdti_trk1 = stuffp->di.n_last;
362     			xtrace(PLAYTRK, "ioctl() track %d to %d\n",
363     			       ti->cdti_trk0, ti->cdti_trk1);
364     			return mcdx_playtrk(stuffp, ti);
365     		}
366     
367     	case CDROMPLAYMSF:{
368     			struct cdrom_msf *msf = (struct cdrom_msf *) arg;
369     
370     			xtrace(IOCTL, "ioctl() PLAYMSF\n");
371     
372     			if ((stuffp->audiostatus == CDROM_AUDIO_PLAY)
373     			    && (-1 == mcdx_hold(stuffp, 1)))
374     				return -EIO;
375     
376     			msf->cdmsf_min0 = uint2bcd(msf->cdmsf_min0);
377     			msf->cdmsf_sec0 = uint2bcd(msf->cdmsf_sec0);
378     			msf->cdmsf_frame0 = uint2bcd(msf->cdmsf_frame0);
379     
380     			msf->cdmsf_min1 = uint2bcd(msf->cdmsf_min1);
381     			msf->cdmsf_sec1 = uint2bcd(msf->cdmsf_sec1);
382     			msf->cdmsf_frame1 = uint2bcd(msf->cdmsf_frame1);
383     
384     			stuffp->stop.dt.minute = msf->cdmsf_min1;
385     			stuffp->stop.dt.second = msf->cdmsf_sec1;
386     			stuffp->stop.dt.frame = msf->cdmsf_frame1;
387     
388     			return mcdx_playmsf(stuffp, msf);
389     		}
390     
391     	case CDROMRESUME:{
392     			xtrace(IOCTL, "ioctl() RESUME\n");
393     			return mcdx_playtrk(stuffp, NULL);
394     		}
395     
396     	case CDROMREADTOCENTRY:{
397     			struct cdrom_tocentry *entry =
398     			    (struct cdrom_tocentry *) arg;
399     			struct s_subqcode *tp = NULL;
400     			xtrace(IOCTL, "ioctl() READTOCENTRY\n");
401     
402     			if (-1 == mcdx_readtoc(stuffp))
403     				return -1;
404     			if (entry->cdte_track == CDROM_LEADOUT)
405     				tp = &stuffp->toc[stuffp->di.n_last -
406     						  stuffp->di.n_first + 1];
407     			else if (entry->cdte_track > stuffp->di.n_last
408     				 || entry->cdte_track < stuffp->di.n_first)
409     				return -EINVAL;
410     			else
411     				tp = &stuffp->toc[entry->cdte_track -
412     						  stuffp->di.n_first];
413     
414     			if (NULL == tp)
415     				return -EIO;
416     			entry->cdte_adr = tp->control;
417     			entry->cdte_ctrl = tp->control >> 4;
418     			/* Always return stuff in MSF, and let the Uniform cdrom driver
419     			   worry about what the user actually wants */
420     			entry->cdte_addr.msf.minute =
421     			    bcd2uint(tp->dt.minute);
422     			entry->cdte_addr.msf.second =
423     			    bcd2uint(tp->dt.second);
424     			entry->cdte_addr.msf.frame =
425     			    bcd2uint(tp->dt.frame);
426     			return 0;
427     		}
428     
429     	case CDROMSUBCHNL:{
430     			struct cdrom_subchnl *sub =
431     			    (struct cdrom_subchnl *) arg;
432     			struct s_subqcode q;
433     
434     			xtrace(IOCTL, "ioctl() SUBCHNL\n");
435     
436     			if (-1 == mcdx_requestsubqcode(stuffp, &q, 2))
437     				return -EIO;
438     
439     			xtrace(SUBCHNL, "audiostatus: %x\n",
440     			       stuffp->audiostatus);
441     			sub->cdsc_audiostatus = stuffp->audiostatus;
442     			sub->cdsc_adr = q.control;
443     			sub->cdsc_ctrl = q.control >> 4;
444     			sub->cdsc_trk = bcd2uint(q.tno);
445     			sub->cdsc_ind = bcd2uint(q.index);
446     
447     			xtrace(SUBCHNL, "trk %d, ind %d\n",
448     			       sub->cdsc_trk, sub->cdsc_ind);
449     			/* Always return stuff in MSF, and let the Uniform cdrom driver
450     			   worry about what the user actually wants */
451     			sub->cdsc_absaddr.msf.minute =
452     			    bcd2uint(q.dt.minute);
453     			sub->cdsc_absaddr.msf.second =
454     			    bcd2uint(q.dt.second);
455     			sub->cdsc_absaddr.msf.frame = bcd2uint(q.dt.frame);
456     			sub->cdsc_reladdr.msf.minute =
457     			    bcd2uint(q.tt.minute);
458     			sub->cdsc_reladdr.msf.second =
459     			    bcd2uint(q.tt.second);
460     			sub->cdsc_reladdr.msf.frame = bcd2uint(q.tt.frame);
461     			xtrace(SUBCHNL,
462     			       "msf: abs %02d:%02d:%02d, rel %02d:%02d:%02d\n",
463     			       sub->cdsc_absaddr.msf.minute,
464     			       sub->cdsc_absaddr.msf.second,
465     			       sub->cdsc_absaddr.msf.frame,
466     			       sub->cdsc_reladdr.msf.minute,
467     			       sub->cdsc_reladdr.msf.second,
468     			       sub->cdsc_reladdr.msf.frame);
469     
470     			return 0;
471     		}
472     
473     	case CDROMREADTOCHDR:{
474     			struct cdrom_tochdr *toc =
475     			    (struct cdrom_tochdr *) arg;
476     
477     			xtrace(IOCTL, "ioctl() READTOCHDR\n");
478     			toc->cdth_trk0 = stuffp->di.n_first;
479     			toc->cdth_trk1 = stuffp->di.n_last;
480     			xtrace(TOCHDR,
481     			       "ioctl() track0 = %d, track1 = %d\n",
482     			       stuffp->di.n_first, stuffp->di.n_last);
483     			return 0;
484     		}
485     
486     	case CDROMPAUSE:{
487     			xtrace(IOCTL, "ioctl() PAUSE\n");
488     			if (stuffp->audiostatus != CDROM_AUDIO_PLAY)
489     				return -EINVAL;
490     			if (-1 == mcdx_stop(stuffp, 1))
491     				return -EIO;
492     			stuffp->audiostatus = CDROM_AUDIO_PAUSED;
493     			if (-1 ==
494     			    mcdx_requestsubqcode(stuffp, &stuffp->start,
495     						 1))
496     				return -EIO;
497     			return 0;
498     		}
499     
500     	case CDROMMULTISESSION:{
501     			struct cdrom_multisession *ms =
502     			    (struct cdrom_multisession *) arg;
503     			xtrace(IOCTL, "ioctl() MULTISESSION\n");
504     			/* Always return stuff in LBA, and let the Uniform cdrom driver
505     			   worry about what the user actually wants */
506     			ms->addr.lba = msf2log(&stuffp->multi.msf_last);
507     			ms->xa_flag = !!stuffp->multi.multi;
508     			xtrace(MS,
509     			       "ioctl() (%d, 0x%08x [%02x:%02x.%02x])\n",
510     			       ms->xa_flag, ms->addr.lba,
511     			       stuffp->multi.msf_last.minute,
512     			       stuffp->multi.msf_last.second,
513     			       stuffp->multi.msf_last.frame);
514     
515     			return 0;
516     		}
517     
518     	case CDROMEJECT:{
519     			xtrace(IOCTL, "ioctl() EJECT\n");
520     			if (stuffp->users > 1)
521     				return -EBUSY;
522     			return (mcdx_tray_move(cdi, 1));
523     		}
524     
525     	case CDROMCLOSETRAY:{
526     			xtrace(IOCTL, "ioctl() CDROMCLOSETRAY\n");
527     			return (mcdx_tray_move(cdi, 0));
528     		}
529     
530     	case CDROMVOLCTRL:{
531     			struct cdrom_volctrl *volctrl =
532     			    (struct cdrom_volctrl *) arg;
533     			xtrace(IOCTL, "ioctl() VOLCTRL\n");
534     
535     #if 0				/* not tested! */
536     			/* adjust for the weirdness of workman (md) */
537     			/* can't test it (hs) */
538     			volctrl.channel2 = volctrl.channel1;
539     			volctrl.channel1 = volctrl.channel3 = 0x00;
540     #endif
541     			return mcdx_setattentuator(stuffp, volctrl, 2);
542     		}
543     
544     	default:
545     		return -EINVAL;
546     	}
547     }
548     
549     void do_mcdx_request(request_queue_t * q)
550     {
551     	int dev;
552     	struct s_drive_stuff *stuffp;
553     
554           again:
555     
556     	if (QUEUE_EMPTY) {
557     		xtrace(REQUEST, "end_request(0): CURRENT == NULL\n");
558     		return;
559     	}
560     
561     	if (CURRENT->rq_status == RQ_INACTIVE) {
562     		xtrace(REQUEST,
563     		       "end_request(0): rq_status == RQ_INACTIVE\n");
564     		return;
565     	}
566     
567     	INIT_REQUEST;
568     
569     	dev = MINOR(CURRENT->rq_dev);
570     	stuffp = mcdx_stuffp[dev];
571     
572     	if ((dev < 0)
573     	    || (dev >= MCDX_NDRIVES)
574     	    || !stuffp || (!stuffp->present)) {
575     		xwarn("do_request(): bad device: %s\n",
576     		      kdevname(CURRENT->rq_dev));
577     		xtrace(REQUEST, "end_request(0): bad device\n");
578     		end_request(0);
579     		return;
580     	}
581     
582     	if (stuffp->audio) {
583     		xwarn("do_request() attempt to read from audio cd\n");
584     		xtrace(REQUEST, "end_request(0): read from audio\n");
585     		end_request(0);
586     		return;
587     	}
588     
589     	xtrace(REQUEST, "do_request() (%lu + %lu)\n",
590     	       CURRENT->sector, CURRENT->nr_sectors);
591     
592     	switch (CURRENT->cmd) {
593     	case WRITE:
594     		xwarn("do_request(): attempt to write to cd!!\n");
595     		xtrace(REQUEST, "end_request(0): write\n");
596     		end_request(0);
597     		return;
598     
599     	case READ:
600     		stuffp->status = 0;
601     		while (CURRENT->nr_sectors) {
602     			int i;
603     
604     			i = mcdx_transfer(stuffp,
605     					  CURRENT->buffer,
606     					  CURRENT->sector,
607     					  CURRENT->nr_sectors);
608     
609     			if (i == -1) {
610     				end_request(0);
611     				goto again;
612     			}
613     			CURRENT->sector += i;
614     			CURRENT->nr_sectors -= i;
615     			CURRENT->buffer += (i * 512);
616     		}
617     		end_request(1);
618     		goto again;
619     
620     		xtrace(REQUEST, "end_request(1)\n");
621     		end_request(1);
622     		break;
623     
624     	default:
625     		panic(MCDX "do_request: unknown command.\n");
626     		break;
627     	}
628     
629     	goto again;
630     }
631     
632     static int mcdx_open(struct cdrom_device_info *cdi, int purpose)
633     {
634     	struct s_drive_stuff *stuffp;
635     	xtrace(OPENCLOSE, "open()\n");
636     	stuffp = mcdx_stuffp[MINOR(cdi->dev)];
637     	if (!stuffp->present)
638     		return -ENXIO;
639     
640     	/* Make the modules looking used ... (thanx bjorn).
641     	 * But we shouldn't forget to decrement the module counter
642     	 * on error return */
643     	MOD_INC_USE_COUNT;
644     
645     	/* this is only done to test if the drive talks with us */
646     	if (-1 == mcdx_getstatus(stuffp, 1)) {
647     		MOD_DEC_USE_COUNT;
648     		return -EIO;
649     	}
650     
651     	if (stuffp->xxx) {
652     
653     		xtrace(OPENCLOSE, "open() media changed\n");
654     		stuffp->audiostatus = CDROM_AUDIO_INVALID;
655     		stuffp->readcmd = 0;
656     		xtrace(OPENCLOSE, "open() Request multisession info\n");
657     		if (-1 ==
658     		    mcdx_requestmultidiskinfo(stuffp, &stuffp->multi, 6))
659     			xinfo("No multidiskinfo\n");
660     	} else {
661     		/* multisession ? */
662     		if (!stuffp->multi.multi)
663     			stuffp->multi.msf_last.second = 2;
664     
665     		xtrace(OPENCLOSE, "open() MS: %d, last @ %02x:%02x.%02x\n",
666     		       stuffp->multi.multi,
667     		       stuffp->multi.msf_last.minute,
668     		       stuffp->multi.msf_last.second,
669     		       stuffp->multi.msf_last.frame);
670     
671     		{;
672     		}		/* got multisession information */
673     		/* request the disks table of contents (aka diskinfo) */
674     		if (-1 == mcdx_requesttocdata(stuffp, &stuffp->di, 1)) {
675     
676     			stuffp->lastsector = -1;
677     
678     		} else {
679     
680     			stuffp->lastsector = (CD_FRAMESIZE / 512)
681     			    * msf2log(&stuffp->di.msf_leadout) - 1;
682     
683     			xtrace(OPENCLOSE,
684     			       "open() start %d (%02x:%02x.%02x) %d\n",
685     			       stuffp->di.n_first,
686     			       stuffp->di.msf_first.minute,
687     			       stuffp->di.msf_first.second,
688     			       stuffp->di.msf_first.frame,
689     			       msf2log(&stuffp->di.msf_first));
690     			xtrace(OPENCLOSE,
691     			       "open() last %d (%02x:%02x.%02x) %d\n",
692     			       stuffp->di.n_last,
693     			       stuffp->di.msf_leadout.minute,
694     			       stuffp->di.msf_leadout.second,
695     			       stuffp->di.msf_leadout.frame,
696     			       msf2log(&stuffp->di.msf_leadout));
697     		}
698     
699     		if (stuffp->toc) {
700     			xtrace(MALLOC, "open() free old toc @ %p\n",
701     			       stuffp->toc);
702     			kfree(stuffp->toc);
703     
704     			stuffp->toc = NULL;
705     		}
706     
707     		xtrace(OPENCLOSE, "open() init irq generation\n");
708     		if (-1 == mcdx_config(stuffp, 1)) {
709     			MOD_DEC_USE_COUNT;
710     			return -EIO;
711     		}
712     #if FALLBACK
713     		/* Set the read speed */
714     		xwarn("AAA %x AAA\n", stuffp->readcmd);
715     		if (stuffp->readerrs)
716     			stuffp->readcmd = READ1X;
717     		else
718     			stuffp->readcmd =
719     			    stuffp->present | SINGLE ? READ1X : READ2X;
720     		xwarn("XXX %x XXX\n", stuffp->readcmd);
721     #else
722     		stuffp->readcmd =
723     		    stuffp->present | SINGLE ? READ1X : READ2X;
724     #endif
725     
726     		/* try to get the first sector, iff any ... */
727     		if (stuffp->lastsector >= 0) {
728     			char buf[512];
729     			int ans;
730     			int tries;
731     
732     			stuffp->xa = 0;
733     			stuffp->audio = 0;
734     
735     			for (tries = 6; tries; tries--) {
736     
737     				stuffp->introk = 1;
738     
739     				xtrace(OPENCLOSE, "open() try as %s\n",
740     				       stuffp->xa ? "XA" : "normal");
741     				/* set data mode */
742     				if (-1 == (ans = mcdx_setdatamode(stuffp,
743     								  stuffp->
744     								  xa ?
745     								  MODE2 :
746     								  MODE1,
747     								  1))) {
748     					/* MOD_DEC_USE_COUNT, return -EIO; */
749     					stuffp->xa = 0;
750     					break;
751     				}
752     
753     				if ((stuffp->audio = e_audio(ans)))
754     					break;
755     
756     				while (0 ==
757     				       (ans =
758     					mcdx_transfer(stuffp, buf, 0, 1)));
759     
760     				if (ans == 1)
761     					break;
762     				stuffp->xa = !stuffp->xa;
763     			}
764     		}
765     		/* xa disks will be read in raw mode, others not */
766     		if (-1 == mcdx_setdrivemode(stuffp,
767     					    stuffp->xa ? RAW : COOKED,
768     					    1)) {
769     			MOD_DEC_USE_COUNT;
770     			return -EIO;
771     		}
772     		if (stuffp->audio) {
773     			xinfo("open() audio disk found\n");
774     		} else if (stuffp->lastsector >= 0) {
775     			xinfo("open() %s%s disk found\n",
776     			      stuffp->xa ? "XA / " : "",
777     			      stuffp->multi.
778     			      multi ? "Multi Session" : "Single Session");
779     		}
780     	}
781     	stuffp->xxx = 0;
782     	stuffp->users++;
783     	return 0;
784     }
785     
786     static void mcdx_close(struct cdrom_device_info *cdi)
787     {
788     	struct s_drive_stuff *stuffp;
789     
790     	xtrace(OPENCLOSE, "close()\n");
791     
792     	stuffp = mcdx_stuffp[MINOR(cdi->dev)];
793     
794     	--stuffp->users;
795     
796     	MOD_DEC_USE_COUNT;
797     }
798     
799     static int mcdx_media_changed(struct cdrom_device_info *cdi, int disc_nr)
800     /*	Return: 1 if media changed since last call to this function
801     			0 otherwise */
802     {
803     	struct s_drive_stuff *stuffp;
804     
805     	xinfo("mcdx_media_changed called for device %s\n",
806     	      kdevname(cdi->dev));
807     
808     	stuffp = mcdx_stuffp[MINOR(cdi->dev)];
809     	mcdx_getstatus(stuffp, 1);
810     
811     	if (stuffp->yyy == 0)
812     		return 0;
813     
814     	stuffp->yyy = 0;
815     	return 1;
816     }
817     
818     #ifndef MODULE
819     static int __init mcdx_setup(char *str)
820     {
821     	int pi[4];
822     	(void) get_options(str, ARRAY_SIZE(pi), pi);
823     
824     	if (pi[0] > 0)
825     		mcdx_drive_map[0][0] = pi[1];
826     	if (pi[0] > 1)
827     		mcdx_drive_map[0][1] = pi[2];
828     	return 1;
829     }
830     
831     __setup("mcdx=", mcdx_setup);
832     
833     #endif
834     
835     /* DIRTY PART ******************************************************/
836     
837     static void mcdx_delay(struct s_drive_stuff *stuff, long jifs)
838     /* This routine is used for sleeping.
839      * A jifs value <0 means NO sleeping,
840      *              =0 means minimal sleeping (let the kernel
841      *                 run for other processes)
842      *              >0 means at least sleep for that amount.
843      *	May be we could use a simple count loop w/ jumps to itself, but
844      *	I wanna make this independent of cpu speed. [1 jiffy is 1/HZ] sec */
845     {
846     	if (jifs < 0)
847     		return;
848     
849     	xtrace(SLEEP, "*** delay: sleepq\n");
850     	interruptible_sleep_on_timeout(&stuff->sleepq, jifs);
851     	xtrace(SLEEP, "delay awoken\n");
852     	if (signal_pending(current)) {
853     		xtrace(SLEEP, "got signal\n");
854     	}
855     }
856     
857     static void mcdx_intr(int irq, void *dev_id, struct pt_regs *regs)
858     {
859     	struct s_drive_stuff *stuffp;
860     	unsigned char b;
861     
862     	stuffp = mcdx_irq_map[irq];
863     
864     	if (stuffp == NULL) {
865     		xwarn("mcdx: no device for intr %d\n", irq);
866     		return;
867     	}
868     #ifdef AK2
869     	if (!stuffp->busy && stuffp->pending)
870     		stuffp->int_err = 1;
871     
872     #endif				/* AK2 */
873     	/* get the interrupt status */
874     	b = inb((unsigned int) stuffp->rreg_status);
875     	stuffp->introk = ~b & MCDX_RBIT_DTEN;
876     
877     	/* NOTE: We only should get interrupts if the data we
878     	 * requested are ready to transfer.
879     	 * But the drive seems to generate ``asynchronous'' interrupts
880     	 * on several error conditions too.  (Despite the err int enable
881     	 * setting during initialisation) */
882     
883     	/* if not ok, read the next byte as the drives status */
884     	if (!stuffp->introk) {
885     		xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b);
886     		if (~b & MCDX_RBIT_STEN) {
887     			xinfo("intr() irq %d    status 0x%02x\n",
888     			      irq, inb((unsigned int) stuffp->rreg_data));
889     		} else {
890     			xinfo("intr() irq %d ambiguous hw status\n", irq);
891     		}
892     	} else {
893     		xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b);
894     	}
895     
896     	stuffp->busy = 0;
897     	wake_up_interruptible(&stuffp->busyq);
898     }
899     
900     
901     static int mcdx_talk(struct s_drive_stuff *stuffp,
902     	  const unsigned char *cmd, size_t cmdlen,
903     	  void *buffer, size_t size, unsigned int timeout, int tries)
904     /* Send a command to the drive, wait for the result.
905      * returns -1 on timeout, drive status otherwise
906      * If buffer is not zero, the result (length size) is stored there.
907      * If buffer is zero the size should be the number of bytes to read
908      * from the drive.  These bytes are discarded.
909      */
910     {
911     	int st;
912     	char c;
913     	int discard;
914     
915     	/* Somebody wants the data read? */
916     	if ((discard = (buffer == NULL)))
917     		buffer = &c;
918     
919     	while (stuffp->lock) {
920     		xtrace(SLEEP, "*** talk: lockq\n");
921     		interruptible_sleep_on(&stuffp->lockq);
922     		xtrace(SLEEP, "talk: awoken\n");
923     	}
924     
925     	stuffp->lock = 1;
926     
927     	/* An operation other then reading data destroys the
928     	   * data already requested and remembered in stuffp->request, ... */
929     	stuffp->valid = 0;
930     
931     #if MCDX_DEBUG & TALK
932     	{
933     		unsigned char i;
934     		xtrace(TALK,
935     		       "talk() %d / %d tries, res.size %d, command 0x%02x",
936     		       tries, timeout, size, (unsigned char) cmd[0]);
937     		for (i = 1; i < cmdlen; i++)
938     			xtrace(TALK, " 0x%02x", cmd[i]);
939     		xtrace(TALK, "\n");
940     	}
941     #endif
942     
943     	/*  give up if all tries are done (bad) or if the status
944     	 *  st != -1 (good) */
945     	for (st = -1; st == -1 && tries; tries--) {
946     
947     		char *bp = (char *) buffer;
948     		size_t sz = size;
949     
950     		outsb((unsigned int) stuffp->wreg_data, cmd, cmdlen);
951     		xtrace(TALK, "talk() command sent\n");
952     
953     		/* get the status byte */
954     		if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
955     			xinfo("talk() %02x timed out (status), %d tr%s left\n",
956     			     cmd[0], tries - 1, tries == 2 ? "y" : "ies");
957     			continue;
958     		}
959     		st = *bp;
960     		sz--;
961     		if (!discard)
962     			bp++;
963     
964     		xtrace(TALK, "talk() got status 0x%02x\n", st);
965     
966     		/* command error? */
967     		if (e_cmderr(st)) {
968     			xwarn("command error cmd = %02x %s \n",
969     			      cmd[0], cmdlen > 1 ? "..." : "");
970     			st = -1;
971     			continue;
972     		}
973     
974     		/* audio status? */
975     		if (stuffp->audiostatus == CDROM_AUDIO_INVALID)
976     			stuffp->audiostatus =
977     			    e_audiobusy(st) ? CDROM_AUDIO_PLAY :
978     			    CDROM_AUDIO_NO_STATUS;
979     		else if (stuffp->audiostatus == CDROM_AUDIO_PLAY
980     			 && e_audiobusy(st) == 0)
981     			stuffp->audiostatus = CDROM_AUDIO_COMPLETED;
982     
983     		/* media change? */
984     		if (e_changed(st)) {
985     			xinfo("talk() media changed\n");
986     			stuffp->xxx = stuffp->yyy = 1;
987     		}
988     
989     		/* now actually get the data */
990     		while (sz--) {
991     			if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
992     				xinfo("talk() %02x timed out (data), %d tr%s left\n",
993     				     cmd[0], tries - 1,
994     				     tries == 2 ? "y" : "ies");
995     				st = -1;
996     				break;
997     			}
998     			if (!discard)
999     				bp++;
1000     			xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1));
1001     		}
1002     	}
1003     
1004     #if !MCDX_QUIET
1005     	if (!tries && st == -1)
1006     		xinfo("talk() giving up\n");
1007     #endif
1008     
1009     	stuffp->lock = 0;
1010     	wake_up_interruptible(&stuffp->lockq);
1011     
1012     	xtrace(TALK, "talk() done with 0x%02x\n", st);
1013     	return st;
1014     }
1015     
1016     /* MODULE STUFF ***********************************************************/
1017     
1018     EXPORT_NO_SYMBOLS;
1019     
1020     int __mcdx_init(void)
1021     {
1022     	int i;
1023     	int drives = 0;
1024     
1025     	mcdx_init();
1026     	for (i = 0; i < MCDX_NDRIVES; i++) {
1027     		if (mcdx_stuffp[i]) {
1028     			xtrace(INIT, "init_module() drive %d stuff @ %p\n",
1029     			       i, mcdx_stuffp[i]);
1030     			drives++;
1031     		}
1032     	}
1033     
1034     	if (!drives)
1035     		return -EIO;
1036     
1037     	return 0;
1038     }
1039     
1040     void __exit mcdx_exit(void)
1041     {
1042     	int i;
1043     
1044     	xinfo("cleanup_module called\n");
1045     
1046     	for (i = 0; i < MCDX_NDRIVES; i++) {
1047     		struct s_drive_stuff *stuffp;
1048     		if (unregister_cdrom(&mcdx_info)) {
1049     			printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
1050     			return;
1051     		}
1052     		stuffp = mcdx_stuffp[i];
1053     		if (!stuffp)
1054     			continue;
1055     		release_region((unsigned long) stuffp->wreg_data,
1056     			       MCDX_IO_SIZE);
1057     		free_irq(stuffp->irq, NULL);
1058     		if (stuffp->toc) {
1059     			xtrace(MALLOC, "cleanup_module() free toc @ %p\n",
1060     			       stuffp->toc);
1061     			kfree(stuffp->toc);
1062     		}
1063     		xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n",
1064     		       stuffp);
1065     		mcdx_stuffp[i] = NULL;
1066     		kfree(stuffp);
1067     	}
1068     
1069     	if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
1070     		xwarn("cleanup() unregister_blkdev() failed\n");
1071     	}
1072     	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1073     #if !MCDX_QUIET
1074     	else
1075     	xinfo("cleanup() succeeded\n");
1076     #endif
1077     }
1078     
1079     #ifdef MODULE
1080     module_init(__mcdx_init);
1081     #endif
1082     module_exit(mcdx_exit);
1083     
1084     
1085     /* Support functions ************************************************/
1086     
1087     int __init mcdx_init_drive(int drive)
1088     {
1089     	struct s_version version;
1090     	struct s_drive_stuff *stuffp;
1091     	int size = sizeof(*stuffp);
1092     	char msg[80];
1093     
1094     	mcdx_blocksizes[drive] = 0;
1095     
1096     	xtrace(INIT, "init() try drive %d\n", drive);
1097     
1098     	xtrace(INIT, "kmalloc space for stuffpt's\n");
1099     	xtrace(MALLOC, "init() malloc %d bytes\n", size);
1100     	if (!(stuffp = kmalloc(size, GFP_KERNEL))) {
1101     		xwarn("init() malloc failed\n");
1102     		return 1;
1103     	}
1104     
1105     	xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",
1106     	       sizeof(*stuffp), stuffp);
1107     
1108     	/* set default values */
1109     	memset(stuffp, 0, sizeof(*stuffp));
1110     
1111     	stuffp->present = 0;	/* this should be 0 already */
1112     	stuffp->toc = NULL;	/* this should be NULL already */
1113     
1114     	/* setup our irq and i/o addresses */
1115     	stuffp->irq = irq(mcdx_drive_map[drive]);
1116     	stuffp->wreg_data = stuffp->rreg_data =
1117     	    port(mcdx_drive_map[drive]);
1118     	stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
1119     	stuffp->wreg_hcon = stuffp->wreg_reset + 1;
1120     	stuffp->wreg_chn = stuffp->wreg_hcon + 1;
1121     
1122     	init_waitqueue_head(&stuffp->busyq);
1123     	init_waitqueue_head(&stuffp->lockq);
1124     	init_waitqueue_head(&stuffp->sleepq);
1125     
1126     	/* check if i/o addresses are available */
1127     	if (check_region((unsigned int) stuffp->wreg_data, MCDX_IO_SIZE)) {
1128     		xwarn("0x%3p,%d: Init failed. "
1129     		      "I/O ports (0x%3p..0x%3p) already in use.\n",
1130     		      stuffp->wreg_data, stuffp->irq,
1131     		      stuffp->wreg_data,
1132     		      stuffp->wreg_data + MCDX_IO_SIZE - 1);
1133     		xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
1134     		kfree(stuffp);
1135     		xtrace(INIT, "init() continue at next drive\n");
1136     		return 0;	/* next drive */
1137     	}
1138     
1139     	xtrace(INIT, "init() i/o port is available at 0x%3p\n",
1140     	       stuffp->wreg_data);
1141     	xtrace(INIT, "init() hardware reset\n");
1142     	mcdx_reset(stuffp, HARD, 1);
1143     
1144     	xtrace(INIT, "init() get version\n");
1145     	if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
1146     		/* failed, next drive */
1147     		xwarn("%s=0x%3p,%d: Init failed. Can't get version.\n",
1148     		      MCDX, stuffp->wreg_data, stuffp->irq);
1149     		xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
1150     		kfree(stuffp);
1151     		xtrace(INIT, "init() continue at next drive\n");
1152     		return 0;
1153     	}
1154     
1155     	switch (version.code) {
1156     	case 'D':
1157     		stuffp->readcmd = READ2X;
1158     		stuffp->present = DOUBLE | DOOR | MULTI;
1159     		break;
1160     	case 'F':
1161     		stuffp->readcmd = READ1X;
1162     		stuffp->present = SINGLE | DOOR | MULTI;
1163     		break;
1164     	case 'M':
1165     		stuffp->readcmd = READ1X;
1166     		stuffp->present = SINGLE;
1167     		break;
1168     	default:
1169     		stuffp->present = 0;
1170     		break;
1171     	}
1172     
1173     	stuffp->playcmd = READ1X;
1174     
1175     	if (!stuffp->present) {
1176     		xwarn("%s=0x%3p,%d: Init failed. No Mitsumi CD-ROM?.\n",
1177     		      MCDX, stuffp->wreg_data, stuffp->irq);
1178     		kfree(stuffp);
1179     		return 0;	/* next drive */
1180     	}
1181     
1182     	xtrace(INIT, "init() register blkdev\n");
1183     	if (devfs_register_blkdev(MAJOR_NR, "mcdx", &cdrom_fops) != 0) {
1184     		xwarn("%s=0x%3p,%d: Init failed. Can't get major %d.\n",
1185     		      MCDX, stuffp->wreg_data, stuffp->irq, MAJOR_NR);
1186     		kfree(stuffp);
1187     		return 1;
1188     	}
1189     
1190     	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1191     	read_ahead[MAJOR_NR] = READ_AHEAD;
1192     	blksize_size[MAJOR_NR] = mcdx_blocksizes;
1193     
1194     	xtrace(INIT, "init() subscribe irq and i/o\n");
1195     	mcdx_irq_map[stuffp->irq] = stuffp;
1196     	if (request_irq(stuffp->irq, mcdx_intr, SA_INTERRUPT, "mcdx", NULL)) {
1197     		xwarn("%s=0x%3p,%d: Init failed. Can't get irq (%d).\n",
1198     		      MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
1199     		stuffp->irq = 0;
1200     		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1201     		kfree(stuffp);
1202     		return 0;
1203     	}
1204     	request_region((unsigned int) stuffp->wreg_data,
1205     		       MCDX_IO_SIZE, "mcdx");
1206     
1207     	xtrace(INIT, "init() get garbage\n");
1208     	{
1209     		int i;
1210     		mcdx_delay(stuffp, HZ / 2);
1211     		for (i = 100; i; i--)
1212     			(void) inb((unsigned int) stuffp->rreg_status);
1213     	}
1214     
1215     
1216     #if WE_KNOW_WHY
1217     	/* irq 11 -> channel register */
1218     	outb(0x50, (unsigned int) stuffp->wreg_chn);
1219     #endif
1220     
1221     	xtrace(INIT, "init() set non dma but irq mode\n");
1222     	mcdx_config(stuffp, 1);
1223     
1224     	stuffp->minor = drive;
1225     
1226     	sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%3p, irq %d."
1227     		" (Firmware version %c %x)\n",
1228     		stuffp->wreg_data, stuffp->irq, version.code, version.ver);
1229     	mcdx_stuffp[drive] = stuffp;
1230     	xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
1231     	mcdx_info.dev = MKDEV(MAJOR_NR, 0);
1232     	if (register_cdrom(&mcdx_info) != 0) {
1233     		printk("Cannot register Mitsumi CD-ROM!\n");
1234     		release_region((unsigned long) stuffp->wreg_data,
1235     			       MCDX_IO_SIZE);
1236     		free_irq(stuffp->irq, NULL);
1237     		kfree(stuffp);
1238     		if (devfs_unregister_blkdev(MAJOR_NR, "mcdx") != 0)
1239     			xwarn("cleanup() unregister_blkdev() failed\n");
1240     		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1241     		return 2;
1242     	}
1243     	printk(msg);
1244     	return 0;
1245     }
1246     
1247     int __init mcdx_init(void)
1248     {
1249     	int drive;
1250     #ifdef MODULE
1251     	xwarn("Version 2.14(hs) for " UTS_RELEASE "\n");
1252     #else
1253     	xwarn("Version 2.14(hs) \n");
1254     #endif
1255     
1256     	xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n");
1257     
1258     	/* zero the pointer array */
1259     	for (drive = 0; drive < MCDX_NDRIVES; drive++)
1260     		mcdx_stuffp[drive] = NULL;
1261     
1262     	/* do the initialisation */
1263     	for (drive = 0; drive < MCDX_NDRIVES; drive++) {
1264     		switch (mcdx_init_drive(drive)) {
1265     		case 2:
1266     			return -EIO;
1267     		case 1:
1268     			break;
1269     		}
1270     	}
1271     	return 0;
1272     }
1273     
1274     static int mcdx_transfer(struct s_drive_stuff *stuffp,
1275     	      char *p, int sector, int nr_sectors)
1276     /*	This seems to do the actually transfer.  But it does more.  It
1277     	keeps track of errors occurred and will (if possible) fall back
1278     	to single speed on error.
1279     	Return:	-1 on timeout or other error
1280     			else status byte (as in stuff->st) */
1281     {
1282     	int ans;
1283     
1284     	ans = mcdx_xfer(stuffp, p, sector, nr_sectors);
1285     	return ans;
1286     #if FALLBACK
1287     	if (-1 == ans)
1288     		stuffp->readerrs++;
1289     	else
1290     		return ans;
1291     
1292     	if (stuffp->readerrs && stuffp->readcmd == READ1X) {
1293     		xwarn("XXX Already reading 1x -- no chance\n");
1294     		return -1;
1295     	}
1296     
1297     	xwarn("XXX Fallback to 1x\n");
1298     
1299     	stuffp->readcmd = READ1X;
1300     	return mcdx_transfer(stuffp, p, sector, nr_sectors);
1301     #endif
1302     
1303     }
1304     
1305     
1306     static int mcdx_xfer(struct s_drive_stuff *stuffp,
1307     		     char *p, int sector, int nr_sectors)
1308     /*	This does actually the transfer from the drive.
1309     	Return:	-1 on timeout or other error
1310     			else status byte (as in stuff->st) */
1311     {
1312     	int border;
1313     	int done = 0;
1314     	long timeout;
1315     
1316     	if (stuffp->audio) {
1317     		xwarn("Attempt to read from audio CD.\n");
1318     		return -1;
1319     	}
1320     
1321     	if (!stuffp->readcmd) {
1322     		xinfo("Can't transfer from missing disk.\n");
1323     		return -1;
1324     	}
1325     
1326     	while (stuffp->lock) {
1327     		interruptible_sleep_on(&stuffp->lockq);
1328     	}
1329     
1330     	if (stuffp->valid && (sector >= stuffp->pending)
1331     	    && (sector < stuffp->low_border)) {
1332     
1333     		/* All (or at least a part of the sectors requested) seems
1334     		   * to be already requested, so we don't need to bother the
1335     		   * drive with new requests ...
1336     		   * Wait for the drive become idle, but first
1337     		   * check for possible occurred errors --- the drive
1338     		   * seems to report them asynchronously */
1339     
1340     
1341     		border = stuffp->high_border < (border =
1342     						sector + nr_sectors)
1343     		    ? stuffp->high_border : border;
1344     
1345     		stuffp->lock = current->pid;
1346     
1347     		do {
1348     
1349     			while (stuffp->busy) {
1350     
1351     				timeout =
1352     				    interruptible_sleep_on_timeout
1353     				    (&stuffp->busyq, 5 * HZ);
1354     
1355     				if (!stuffp->introk) {
1356     					xtrace(XFER,
1357     					       "error via interrupt\n");
1358     				} else if (!timeout) {
1359     					xtrace(XFER, "timeout\n");
1360     				} else if (signal_pending(current)) {
1361     					xtrace(XFER, "signal\n");
1362     				} else
1363     					continue;
1364     
1365     				stuffp->lock = 0;
1366     				stuffp->busy = 0;
1367     				stuffp->valid = 0;
1368     
1369     				wake_up_interruptible(&stuffp->lockq);
1370     				xtrace(XFER, "transfer() done (-1)\n");
1371     				return -1;
1372     			}
1373     
1374     			/* check if we need to set the busy flag (as we
1375     			 * expect an interrupt */
1376     			stuffp->busy = (3 == (stuffp->pending & 3));
1377     
1378     			/* Test if it's the first sector of a block,
1379     			 * there we have to skip some bytes as we read raw data */
1380     			if (stuffp->xa && (0 == (stuffp->pending & 3))) {
1381     				const int HEAD =
1382     				    CD_FRAMESIZE_RAW - CD_XA_TAIL -
1383     				    CD_FRAMESIZE;
1384     				insb((unsigned int) stuffp->rreg_data, p,
1385     				     HEAD);
1386     			}
1387     
1388     			/* now actually read the data */
1389     			insb((unsigned int) stuffp->rreg_data, p, 512);
1390     
1391     			/* test if it's the last sector of a block,
1392     			 * if so, we have to handle XA special */
1393     			if ((3 == (stuffp->pending & 3)) && stuffp->xa) {
1394     				char dummy[CD_XA_TAIL];
1395     				insb((unsigned int) stuffp->rreg_data,
1396     				     &dummy[0], CD_XA_TAIL);
1397     			}
1398     
1399     			if (stuffp->pending == sector) {
1400     				p += 512;
1401     				done++;
1402     				sector++;
1403     			}
1404     		} while (++(stuffp->pending) < border);
1405     
1406     		stuffp->lock = 0;
1407     		wake_up_interruptible(&stuffp->lockq);
1408     
1409     	} else {
1410     
1411     		/* The requested sector(s) is/are out of the
1412     		 * already requested range, so we have to bother the drive
1413     		 * with a new request. */
1414     
1415     		static unsigned char cmd[] = {
1416     			0,
1417     			0, 0, 0,
1418     			0, 0, 0
1419     		};
1420     
1421     		cmd[0] = stuffp->readcmd;
1422     
1423     		/* The numbers held in ->pending, ..., should be valid */
1424     		stuffp->valid = 1;
1425     		stuffp->pending = sector & ~3;
1426     
1427     		/* do some sanity checks */
1428     		if (stuffp->pending > stuffp->lastsector) {
1429     			xwarn
1430     			    ("transfer() sector %d from nirvana requested.\n",
1431     			     stuffp->pending);
1432     			stuffp->status = MCDX_ST_EOM;
1433     			stuffp->valid = 0;
1434     			xtrace(XFER, "transfer() done (-1)\n");
1435     			return -1;
1436     		}
1437     
1438     		if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE)
1439     		    > stuffp->lastsector + 1) {
1440     			xtrace(XFER, "cut low_border\n");
1441     			stuffp->low_border = stuffp->lastsector + 1;
1442     		}
1443     		if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE)
1444     		    > stuffp->lastsector + 1) {
1445     			xtrace(XFER, "cut high_border\n");
1446     			stuffp->high_border = stuffp->lastsector + 1;
1447     		}
1448     
1449     		{		/* Convert the sector to be requested to MSF format */
1450     			struct cdrom_msf0 pending;
1451     			log2msf(stuffp->pending / 4, &pending);
1452     			cmd[1] = pending.minute;
1453     			cmd[2] = pending.second;
1454     			cmd[3] = pending.frame;
1455     		}
1456     
1457     		cmd[6] =
1458     		    (unsigned
1459     		     char) ((stuffp->high_border - stuffp->pending) / 4);
1460     		xtrace(XFER, "[%2d]\n", cmd[6]);
1461     
1462     		stuffp->busy = 1;
1463     		/* Now really issue the request command */
1464     		outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd);
1465     
1466     	}
1467     #ifdef AK2
1468     	if (stuffp->int_err) {
1469     		stuffp->valid = 0;
1470     		stuffp->int_err = 0;
1471     		return -1;
1472     	}
1473     #endif				/* AK2 */
1474     
1475     	stuffp->low_border = (stuffp->low_border +=
1476     			      done) <
1477     	    stuffp->high_border ? stuffp->low_border : stuffp->high_border;
1478     
1479     	return done;
1480     }
1481     
1482     
1483     /*	Access to elements of the mcdx_drive_map members */
1484     
1485     static char *port(int *ip)
1486     {
1487     	return (char *) ip[0];
1488     }
1489     static int irq(int *ip)
1490     {
1491     	return ip[1];
1492     }
1493     
1494     /*	Misc number converters */
1495     
1496     static unsigned int bcd2uint(unsigned char c)
1497     {
1498     	return (c >> 4) * 10 + (c & 0x0f);
1499     }
1500     
1501     static unsigned int uint2bcd(unsigned int ival)
1502     {
1503     	return ((ival / 10) << 4) | (ival % 10);
1504     }
1505     
1506     static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf)
1507     {
1508     	l += CD_MSF_OFFSET;
1509     	pmsf->minute = uint2bcd(l / 4500), l %= 4500;
1510     	pmsf->second = uint2bcd(l / 75);
1511     	pmsf->frame = uint2bcd(l % 75);
1512     }
1513     
1514     static unsigned int msf2log(const struct cdrom_msf0 *pmsf)
1515     {
1516     	return bcd2uint(pmsf->frame)
1517     	    + bcd2uint(pmsf->second) * 75
1518     	    + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET;
1519     }
1520     
1521     int mcdx_readtoc(struct s_drive_stuff *stuffp)
1522     /*  Read the toc entries from the CD,
1523      *  Return: -1 on failure, else 0 */
1524     {
1525     
1526     	if (stuffp->toc) {
1527     		xtrace(READTOC, "ioctl() toc already read\n");
1528     		return 0;
1529     	}
1530     
1531     	xtrace(READTOC, "ioctl() readtoc for %d tracks\n",
1532     	       stuffp->di.n_last - stuffp->di.n_first + 1);
1533     
1534     	if (-1 == mcdx_hold(stuffp, 1))
1535     		return -1;
1536     
1537     	xtrace(READTOC, "ioctl() tocmode\n");
1538     	if (-1 == mcdx_setdrivemode(stuffp, TOC, 1))
1539     		return -EIO;
1540     
1541     	/* all seems to be ok so far ... malloc */
1542     	{
1543     		int size;
1544     		size =
1545     		    sizeof(struct s_subqcode) * (stuffp->di.n_last -
1546     						 stuffp->di.n_first + 2);
1547     
1548     		xtrace(MALLOC, "ioctl() malloc %d bytes\n", size);
1549     		stuffp->toc = kmalloc(size, GFP_KERNEL);
1550     		if (!stuffp->toc) {
1551     			xwarn("Cannot malloc %d bytes for toc\n", size);
1552     			mcdx_setdrivemode(stuffp, DATA, 1);
1553     			return -EIO;
1554     		}
1555     	}
1556     
1557     	/* now read actually the index */
1558     	{
1559     		int trk;
1560     		int retries;
1561     
1562     		for (trk = 0;
1563     		     trk < (stuffp->di.n_last - stuffp->di.n_first + 1);
1564     		     trk++)
1565     			stuffp->toc[trk].index = 0;
1566     
1567     		for (retries = 300; retries; retries--) {	/* why 300? */
1568     			struct s_subqcode q;
1569     			unsigned int idx;
1570     
1571     			if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) {
1572     				mcdx_setdrivemode(stuffp, DATA, 1);
1573     				return -EIO;
1574     			}
1575     
1576     			idx = bcd2uint(q.index);
1577     
1578     			if ((idx > 0)
1579     			    && (idx <= stuffp->di.n_last)
1580     			    && (q.tno == 0)
1581     			    && (stuffp->toc[idx - stuffp->di.n_first].
1582     				index == 0)) {
1583     				stuffp->toc[idx - stuffp->di.n_first] = q;
1584     				xtrace(READTOC,
1585     				       "ioctl() toc idx %d (trk %d)\n",
1586     				       idx, trk);
1587     				trk--;
1588     			}
1589     			if (trk == 0)
1590     				break;
1591     		}
1592     		memset(&stuffp->
1593     		       toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0,
1594     		       sizeof(stuffp->toc[0]));
1595     		stuffp->toc[stuffp->di.n_last - stuffp->di.n_first +
1596     			    1].dt = stuffp->di.msf_leadout;
1597     	}
1598     
1599     	/* unset toc mode */
1600     	xtrace(READTOC, "ioctl() undo toc mode\n");
1601     	if (-1 == mcdx_setdrivemode(stuffp, DATA, 2))
1602     		return -EIO;
1603     
1604     #if MCDX_DEBUG && READTOC
1605     	{
1606     		int trk;
1607     		for (trk = 0;
1608     		     trk < (stuffp->di.n_last - stuffp->di.n_first + 2);
1609     		     trk++)
1610     			xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x"
1611     			       "  %02x:%02x.%02x  %02x:%02x.%02x\n",
1612     			       trk + stuffp->di.n_first,
1613     			       stuffp->toc[trk].control,
1614     			       stuffp->toc[trk].tno,
1615     			       stuffp->toc[trk].index,
1616     			       stuffp->toc[trk].tt.minute,
1617     			       stuffp->toc[trk].tt.second,
1618     			       stuffp->toc[trk].tt.frame,
1619     			       stuffp->toc[trk].dt.minute,
1620     			       stuffp->toc[trk].dt.second,
1621     			       stuffp->toc[trk].dt.frame);
1622     	}
1623     #endif
1624     
1625     	return 0;
1626     }
1627     
1628     static int
1629     mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf)
1630     {
1631     	unsigned char cmd[7] = {
1632     		0, 0, 0, 0, 0, 0, 0
1633     	};
1634     
1635     	if (!stuffp->readcmd) {
1636     		xinfo("Can't play from missing disk.\n");
1637     		return -1;
1638     	}
1639     
1640     	cmd[0] = stuffp->playcmd;
1641     
1642     	cmd[1] = msf->cdmsf_min0;
1643     	cmd[2] = msf->cdmsf_sec0;
1644     	cmd[3] = msf->cdmsf_frame0;
1645     	cmd[4] = msf->cdmsf_min1;
1646     	cmd[5] = msf->cdmsf_sec1;
1647     	cmd[6] = msf->cdmsf_frame1;
1648     
1649     	xtrace(PLAYMSF, "ioctl(): play %x "
1650     	       "%02x:%02x:%02x -- %02x:%02x:%02x\n",
1651     	       cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
1652     
1653     	outsb((unsigned int) stuffp->wreg_data, cmd, sizeof cmd);
1654     
1655     	if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {
1656     		xwarn("playmsf() timeout\n");
1657     		return -1;
1658     	}
1659     
1660     	stuffp->audiostatus = CDROM_AUDIO_PLAY;
1661     	return 0;
1662     }
1663     
1664     static int
1665     mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti)
1666     {
1667     	struct s_subqcode *p;
1668     	struct cdrom_msf msf;
1669     
1670     	if (-1 == mcdx_readtoc(stuffp))
1671     		return -1;
1672     
1673     	if (ti)
1674     		p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first];
1675     	else
1676     		p = &stuffp->start;
1677     
1678     	msf.cdmsf_min0 = p->dt.minute;
1679     	msf.cdmsf_sec0 = p->dt.second;
1680     	msf.cdmsf_frame0 = p->dt.frame;
1681     
1682     	if (ti) {
1683     		p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1];
1684     		stuffp->stop = *p;
1685     	} else
1686     		p = &stuffp->stop;
1687     
1688     	msf.cdmsf_min1 = p->dt.minute;
1689     	msf.cdmsf_sec1 = p->dt.second;
1690     	msf.cdmsf_frame1 = p->dt.frame;
1691     
1692     	return mcdx_playmsf(stuffp, &msf);
1693     }
1694     
1695     
1696     /* Drive functions ************************************************/
1697     
1698     static int mcdx_tray_move(struct cdrom_device_info *cdi, int position)
1699     {
1700     	struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
1701     
1702     	if (!stuffp->present)
1703     		return -ENXIO;
1704     	if (!(stuffp->present & DOOR))
1705     		return -ENOSYS;
1706     
1707     	if (position)		/* 1: eject */
1708     		return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3);
1709     	else			/* 0: close */
1710     		return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3);
1711     	return 1;
1712     }
1713     
1714     static int mcdx_stop(struct s_drive_stuff *stuffp, int tries)
1715     {
1716     	return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries);
1717     }
1718     
1719     static int mcdx_hold(struct s_drive_stuff *stuffp, int tries)
1720     {
1721     	return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries);
1722     }
1723     
1724     static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
1725     		     struct s_subqcode *sub, int tries)
1726     {
1727     	char buf[11];
1728     	int ans;
1729     
1730     	if (-1 == (ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf),
1731     				   2 * HZ, tries)))
1732     		return -1;
1733     	sub->control = buf[1];
1734     	sub->tno = buf[2];
1735     	sub->index = buf[3];
1736     	sub->tt.minute = buf[4];
1737     	sub->tt.second = buf[5];
1738     	sub->tt.frame = buf[6];
1739     	sub->dt.minute = buf[8];
1740     	sub->dt.second = buf[9];
1741     	sub->dt.frame = buf[10];
1742     
1743     	return ans;
1744     }
1745     
1746     static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp,
1747     			  struct s_multi *multi, int tries)
1748     {
1749     	char buf[5];
1750     	int ans;
1751     
1752     	if (stuffp->present & MULTI) {
1753     		ans =
1754     		    mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ,
1755     			      tries);
1756     		multi->multi = buf[1];
1757     		multi->msf_last.minute = buf[2];
1758     		multi->msf_last.second = buf[3];
1759     		multi->msf_last.frame = buf[4];
1760     		return ans;
1761     	} else {
1762     		multi->multi = 0;
1763     		return 0;
1764     	}
1765     }
1766     
1767     static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info,
1768     		    int tries)
1769     {
1770     	char buf[9];
1771     	int ans;
1772     	ans =
1773     	    mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries);
1774     	if (ans == -1) {
1775     		info->n_first = 0;
1776     		info->n_last = 0;
1777     	} else {
1778     		info->n_first = bcd2uint(buf[1]);
1779     		info->n_last = bcd2uint(buf[2]);
1780     		info->msf_leadout.minute = buf[3];
1781     		info->msf_leadout.second = buf[4];
1782     		info->msf_leadout.frame = buf[5];
1783     		info->msf_first.minute = buf[6];
1784     		info->msf_first.second = buf[7];
1785     		info->msf_first.frame = buf[8];
1786     	}
1787     	return ans;
1788     }
1789     
1790     static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode,
1791     		  int tries)
1792     {
1793     	char cmd[2];
1794     	int ans;
1795     
1796     	xtrace(HW, "setdrivemode() %d\n", mode);
1797     
1798     	if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries)))
1799     		return -1;
1800     
1801     	switch (mode) {
1802     	case TOC:
1803     		cmd[1] |= 0x04;
1804     		break;
1805     	case DATA:
1806     		cmd[1] &= ~0x04;
1807     		break;
1808     	case RAW:
1809     		cmd[1] |= 0x40;
1810     		break;
1811     	case COOKED:
1812     		cmd[1] &= ~0x40;
1813     		break;
1814     	default:
1815     		break;
1816     	}
1817     	cmd[0] = 0x50;
1818     	return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
1819     }
1820     
1821     static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode,
1822     		 int tries)
1823     {
1824     	unsigned char cmd[2] = { 0xa0 };
1825     	xtrace(HW, "setdatamode() %d\n", mode);
1826     	switch (mode) {
1827     	case MODE0:
1828     		cmd[1] = 0x00;
1829     		break;
1830     	case MODE1:
1831     		cmd[1] = 0x01;
1832     		break;
1833     	case MODE2:
1834     		cmd[1] = 0x02;
1835     		break;
1836     	default:
1837     		return -EINVAL;
1838     	}
1839     	return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
1840     }
1841     
1842     static int mcdx_config(struct s_drive_stuff *stuffp, int tries)
1843     {
1844     	char cmd[4];
1845     
1846     	xtrace(HW, "config()\n");
1847     
1848     	cmd[0] = 0x90;
1849     
1850     	cmd[1] = 0x10;		/* irq enable */
1851     	cmd[2] = 0x05;		/* pre, err irq enable */
1852     
1853     	if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries))
1854     		return -1;
1855     
1856     	cmd[1] = 0x02;		/* dma select */
1857     	cmd[2] = 0x00;		/* no dma */
1858     
1859     	return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries);
1860     }
1861     
1862     static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver,
1863     		    int tries)
1864     {
1865     	char buf[3];
1866     	int ans;
1867     
1868     	if (-1 == (ans = mcdx_talk(stuffp, "\xdc",
1869     				   1, buf, sizeof(buf), 2 * HZ, tries)))
1870     		return ans;
1871     
1872     	ver->code = buf[1];
1873     	ver->ver = buf[2];
1874     
1875     	return ans;
1876     }
1877     
1878     static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
1879     {
1880     	if (mode == HARD) {
1881     		outb(0, (unsigned int) stuffp->wreg_chn);	/* no dma, no irq -> hardware */
1882     		outb(0, (unsigned int) stuffp->wreg_reset);	/* hw reset */
1883     		return 0;
1884     	} else
1885     		return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);
1886     }
1887     
1888     static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock)
1889     {
1890     	struct s_drive_stuff *stuffp = mcdx_stuffp[MINOR(cdi->dev)];
1891     	char cmd[2] = { 0xfe };
1892     
1893     	if (!(stuffp->present & DOOR))
1894     		return -ENOSYS;
1895     	if (stuffp->present & DOOR) {
1896     		cmd[1] = lock ? 0x01 : 0x00;
1897     		return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);
1898     	} else
1899     		return 0;
1900     }
1901     
1902     static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries)
1903     {
1904     	return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries);
1905     }
1906     
1907     static int
1908     mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf)
1909     {
1910     	unsigned long timeout = to + jiffies;
1911     	char c;
1912     
1913     	if (!buf)
1914     		buf = &c;
1915     
1916     	while (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_STEN) {
1917     		if (time_after(jiffies, timeout))
1918     			return -1;
1919     		mcdx_delay(stuffp, delay);
1920     	}
1921     
1922     	*buf = (unsigned char) inb((unsigned int) stuffp->rreg_data) & 0xff;
1923     
1924     	return 0;
1925     }
1926     
1927     static int mcdx_setattentuator(struct s_drive_stuff *stuffp,
1928     		    struct cdrom_volctrl *vol, int tries)
1929     {
1930     	char cmd[5];
1931     	cmd[0] = 0xae;
1932     	cmd[1] = vol->channel0;
1933     	cmd[2] = 0;
1934     	cmd[3] = vol->channel1;
1935     	cmd[4] = 0;
1936     
1937     	return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries);
1938     }
1939     
1940     MODULE_LICENSE("GPL");
1941