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