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