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