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