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