fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / cdrom / mcdx.c
1 /*
2  * The Mitsumi CDROM interface
3  * Copyright (C) 1995 1996 Heiko Schlittermann <heiko@lotte.sax.de>
4  * VERSION: 2.14(hs)
5  *
6  * ... anyway, I'm back again, thanks to Marcin, he adopted
7  * large portions of my code (at least the parts containing
8  * my main thoughts ...)
9  *
10  ****************** H E L P *********************************
11  * If you ever plan to update your CD ROM drive and perhaps
12  * want to sell or simply give away your Mitsumi FX-001[DS]
13  * -- Please --
14  * mail me (heiko@lotte.sax.de).  When my last drive goes
15  * ballistic no more driver support will be available from me!
16  *************************************************************
17  *
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 2, or (at your option)
21  * any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; see the file COPYING.  If not, write to
30  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
31  *
32  * Thanks to
33  *  The Linux Community at all and ...
34  *  Martin Harriss (he wrote the first Mitsumi Driver)
35  *  Eberhard Moenkeberg (he gave me much support and the initial kick)
36  *  Bernd Huebner, Ruediger Helsch (Unifix-Software GmbH, they
37  *      improved the original driver)
38  *  Jon Tombs, Bjorn Ekwall (module support)
39  *  Daniel v. Mosnenck (he sent me the Technical and Programming Reference)
40  *  Gerd Knorr (he lent me his PhotoCD)
41  *  Nils Faerber and Roger E. Wolff (extensively tested the LU portion)
42  *  Andreas Kies (testing the mysterious hang-ups)
43  *  Heiko Eissfeldt (VERIFY_READ/WRITE)
44  *  Marcin Dalecki (improved performance, shortened code)
45  *  ... somebody forgotten?
46  *
47  *  9 November 1999 -- Make kernel-parameter implementation work with 2.3.x 
48  *                     Removed init_module & cleanup_module in favor of 
49  *                     module_init & module_exit.
50  *                     Torben Mathiasen <tmm@image.dk>
51  */
52
53
54 #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)
849 {
850         struct s_drive_stuff *stuffp = dev_id;
851         unsigned char b;
852
853 #ifdef AK2
854         if (!stuffp->busy && stuffp->pending)
855                 stuffp->int_err = 1;
856
857 #endif                          /* AK2 */
858         /* get the interrupt status */
859         b = inb(stuffp->rreg_status);
860         stuffp->introk = ~b & MCDX_RBIT_DTEN;
861
862         /* NOTE: We only should get interrupts if the data we
863          * requested are ready to transfer.
864          * But the drive seems to generate ``asynchronous'' interrupts
865          * on several error conditions too.  (Despite the err int enable
866          * setting during initialisation) */
867
868         /* if not ok, read the next byte as the drives status */
869         if (!stuffp->introk) {
870                 xtrace(IRQ, "intr() irq %d hw status 0x%02x\n", irq, b);
871                 if (~b & MCDX_RBIT_STEN) {
872                         xinfo("intr() irq %d    status 0x%02x\n",
873                               irq, inb(stuffp->rreg_data));
874                 } else {
875                         xinfo("intr() irq %d ambiguous hw status\n", irq);
876                 }
877         } else {
878                 xtrace(IRQ, "irq() irq %d ok, status %02x\n", irq, b);
879         }
880
881         stuffp->busy = 0;
882         wake_up_interruptible(&stuffp->busyq);
883         return IRQ_HANDLED;
884 }
885
886
887 static int mcdx_talk(struct s_drive_stuff *stuffp,
888           const unsigned char *cmd, size_t cmdlen,
889           void *buffer, size_t size, unsigned int timeout, int tries)
890 /* Send a command to the drive, wait for the result.
891  * returns -1 on timeout, drive status otherwise
892  * If buffer is not zero, the result (length size) is stored there.
893  * If buffer is zero the size should be the number of bytes to read
894  * from the drive.  These bytes are discarded.
895  */
896 {
897         int st;
898         char c;
899         int discard;
900
901         /* Somebody wants the data read? */
902         if ((discard = (buffer == NULL)))
903                 buffer = &c;
904
905         while (stuffp->lock) {
906                 xtrace(SLEEP, "*** talk: lockq\n");
907                 interruptible_sleep_on(&stuffp->lockq);
908                 xtrace(SLEEP, "talk: awoken\n");
909         }
910
911         stuffp->lock = 1;
912
913         /* An operation other then reading data destroys the
914            * data already requested and remembered in stuffp->request, ... */
915         stuffp->valid = 0;
916
917 #if MCDX_DEBUG & TALK
918         {
919                 unsigned char i;
920                 xtrace(TALK,
921                        "talk() %d / %d tries, res.size %d, command 0x%02x",
922                        tries, timeout, size, (unsigned char) cmd[0]);
923                 for (i = 1; i < cmdlen; i++)
924                         xtrace(TALK, " 0x%02x", cmd[i]);
925                 xtrace(TALK, "\n");
926         }
927 #endif
928
929         /*  give up if all tries are done (bad) or if the status
930          *  st != -1 (good) */
931         for (st = -1; st == -1 && tries; tries--) {
932
933                 char *bp = (char *) buffer;
934                 size_t sz = size;
935
936                 outsb(stuffp->wreg_data, cmd, cmdlen);
937                 xtrace(TALK, "talk() command sent\n");
938
939                 /* get the status byte */
940                 if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
941                         xinfo("talk() %02x timed out (status), %d tr%s left\n",
942                              cmd[0], tries - 1, tries == 2 ? "y" : "ies");
943                         continue;
944                 }
945                 st = *bp;
946                 sz--;
947                 if (!discard)
948                         bp++;
949
950                 xtrace(TALK, "talk() got status 0x%02x\n", st);
951
952                 /* command error? */
953                 if (e_cmderr(st)) {
954                         xwarn("command error cmd = %02x %s \n",
955                               cmd[0], cmdlen > 1 ? "..." : "");
956                         st = -1;
957                         continue;
958                 }
959
960                 /* audio status? */
961                 if (stuffp->audiostatus == CDROM_AUDIO_INVALID)
962                         stuffp->audiostatus =
963                             e_audiobusy(st) ? CDROM_AUDIO_PLAY :
964                             CDROM_AUDIO_NO_STATUS;
965                 else if (stuffp->audiostatus == CDROM_AUDIO_PLAY
966                          && e_audiobusy(st) == 0)
967                         stuffp->audiostatus = CDROM_AUDIO_COMPLETED;
968
969                 /* media change? */
970                 if (e_changed(st)) {
971                         xinfo("talk() media changed\n");
972                         stuffp->xxx = stuffp->yyy = 1;
973                 }
974
975                 /* now actually get the data */
976                 while (sz--) {
977                         if (-1 == mcdx_getval(stuffp, timeout, 0, bp)) {
978                                 xinfo("talk() %02x timed out (data), %d tr%s left\n",
979                                      cmd[0], tries - 1,
980                                      tries == 2 ? "y" : "ies");
981                                 st = -1;
982                                 break;
983                         }
984                         if (!discard)
985                                 bp++;
986                         xtrace(TALK, "talk() got 0x%02x\n", *(bp - 1));
987                 }
988         }
989
990 #if !MCDX_QUIET
991         if (!tries && st == -1)
992                 xinfo("talk() giving up\n");
993 #endif
994
995         stuffp->lock = 0;
996         wake_up_interruptible(&stuffp->lockq);
997
998         xtrace(TALK, "talk() done with 0x%02x\n", st);
999         return st;
1000 }
1001
1002 /* MODULE STUFF ***********************************************************/
1003
1004 static int __init __mcdx_init(void)
1005 {
1006         int i;
1007         int drives = 0;
1008
1009         mcdx_init();
1010         for (i = 0; i < MCDX_NDRIVES; i++) {
1011                 if (mcdx_stuffp[i]) {
1012                         xtrace(INIT, "init_module() drive %d stuff @ %p\n",
1013                                i, mcdx_stuffp[i]);
1014                         drives++;
1015                 }
1016         }
1017
1018         if (!drives)
1019                 return -EIO;
1020
1021         return 0;
1022 }
1023
1024 static void __exit mcdx_exit(void)
1025 {
1026         int i;
1027
1028         xinfo("cleanup_module called\n");
1029
1030         for (i = 0; i < MCDX_NDRIVES; i++) {
1031                 struct s_drive_stuff *stuffp = mcdx_stuffp[i];
1032                 if (!stuffp)
1033                         continue;
1034                 del_gendisk(stuffp->disk);
1035                 if (unregister_cdrom(&stuffp->info)) {
1036                         printk(KERN_WARNING "Can't unregister cdrom mcdx\n");
1037                         continue;
1038                 }
1039                 put_disk(stuffp->disk);
1040                 release_region(stuffp->wreg_data, MCDX_IO_SIZE);
1041                 free_irq(stuffp->irq, NULL);
1042                 if (stuffp->toc) {
1043                         xtrace(MALLOC, "cleanup_module() free toc @ %p\n",
1044                                stuffp->toc);
1045                         kfree(stuffp->toc);
1046                 }
1047                 xtrace(MALLOC, "cleanup_module() free stuffp @ %p\n",
1048                        stuffp);
1049                 mcdx_stuffp[i] = NULL;
1050                 kfree(stuffp);
1051         }
1052
1053         if (unregister_blkdev(MAJOR_NR, "mcdx") != 0) {
1054                 xwarn("cleanup() unregister_blkdev() failed\n");
1055         }
1056         blk_cleanup_queue(mcdx_queue);
1057 #if !MCDX_QUIET
1058         else
1059         xinfo("cleanup() succeeded\n");
1060 #endif
1061 }
1062
1063 #ifdef MODULE
1064 module_init(__mcdx_init);
1065 #endif
1066 module_exit(mcdx_exit);
1067
1068
1069 /* Support functions ************************************************/
1070
1071 static int __init mcdx_init_drive(int drive)
1072 {
1073         struct s_version version;
1074         struct gendisk *disk;
1075         struct s_drive_stuff *stuffp;
1076         int size = sizeof(*stuffp);
1077         char msg[80];
1078
1079         xtrace(INIT, "init() try drive %d\n", drive);
1080
1081         xtrace(INIT, "kmalloc space for stuffpt's\n");
1082         xtrace(MALLOC, "init() malloc %d bytes\n", size);
1083         if (!(stuffp = kzalloc(size, GFP_KERNEL))) {
1084                 xwarn("init() malloc failed\n");
1085                 return 1;
1086         }
1087
1088         disk = alloc_disk(1);
1089         if (!disk) {
1090                 xwarn("init() malloc failed\n");
1091                 kfree(stuffp);
1092                 return 1;
1093         }
1094
1095         xtrace(INIT, "init() got %d bytes for drive stuff @ %p\n",
1096                sizeof(*stuffp), stuffp);
1097
1098         /* set default values */
1099         stuffp->present = 0;    /* this should be 0 already */
1100         stuffp->toc = NULL;     /* this should be NULL already */
1101
1102         /* setup our irq and i/o addresses */
1103         stuffp->irq = irq(mcdx_drive_map[drive]);
1104         stuffp->wreg_data = stuffp->rreg_data = port(mcdx_drive_map[drive]);
1105         stuffp->wreg_reset = stuffp->rreg_status = stuffp->wreg_data + 1;
1106         stuffp->wreg_hcon = stuffp->wreg_reset + 1;
1107         stuffp->wreg_chn = stuffp->wreg_hcon + 1;
1108
1109         init_waitqueue_head(&stuffp->busyq);
1110         init_waitqueue_head(&stuffp->lockq);
1111         init_waitqueue_head(&stuffp->sleepq);
1112
1113         /* check if i/o addresses are available */
1114         if (!request_region(stuffp->wreg_data, MCDX_IO_SIZE, "mcdx")) {
1115                 xwarn("0x%03x,%d: Init failed. "
1116                       "I/O ports (0x%03x..0x%03x) already in use.\n",
1117                       stuffp->wreg_data, stuffp->irq,
1118                       stuffp->wreg_data,
1119                       stuffp->wreg_data + MCDX_IO_SIZE - 1);
1120                 xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
1121                 kfree(stuffp);
1122                 put_disk(disk);
1123                 xtrace(INIT, "init() continue at next drive\n");
1124                 return 0;       /* next drive */
1125         }
1126
1127         xtrace(INIT, "init() i/o port is available at 0x%03x\n"
1128                stuffp->wreg_data);
1129         xtrace(INIT, "init() hardware reset\n");
1130         mcdx_reset(stuffp, HARD, 1);
1131
1132         xtrace(INIT, "init() get version\n");
1133         if (-1 == mcdx_requestversion(stuffp, &version, 4)) {
1134                 /* failed, next drive */
1135                 release_region(stuffp->wreg_data, MCDX_IO_SIZE);
1136                 xwarn("%s=0x%03x,%d: Init failed. Can't get version.\n",
1137                       MCDX, stuffp->wreg_data, stuffp->irq);
1138                 xtrace(MALLOC, "init() free stuffp @ %p\n", stuffp);
1139                 kfree(stuffp);
1140                 put_disk(disk);
1141                 xtrace(INIT, "init() continue at next drive\n");
1142                 return 0;
1143         }
1144
1145         switch (version.code) {
1146         case 'D':
1147                 stuffp->readcmd = READ2X;
1148                 stuffp->present = DOUBLE | DOOR | MULTI;
1149                 break;
1150         case 'F':
1151                 stuffp->readcmd = READ1X;
1152                 stuffp->present = SINGLE | DOOR | MULTI;
1153                 break;
1154         case 'M':
1155                 stuffp->readcmd = READ1X;
1156                 stuffp->present = SINGLE;
1157                 break;
1158         default:
1159                 stuffp->present = 0;
1160                 break;
1161         }
1162
1163         stuffp->playcmd = READ1X;
1164
1165         if (!stuffp->present) {
1166                 release_region(stuffp->wreg_data, MCDX_IO_SIZE);
1167                 xwarn("%s=0x%03x,%d: Init failed. No Mitsumi CD-ROM?.\n",
1168                       MCDX, stuffp->wreg_data, stuffp->irq);
1169                 kfree(stuffp);
1170                 put_disk(disk);
1171                 return 0;       /* next drive */
1172         }
1173
1174         xtrace(INIT, "init() register blkdev\n");
1175         if (register_blkdev(MAJOR_NR, "mcdx")) {
1176                 release_region(stuffp->wreg_data, MCDX_IO_SIZE);
1177                 kfree(stuffp);
1178                 put_disk(disk);
1179                 return 1;
1180         }
1181
1182         mcdx_queue = blk_init_queue(do_mcdx_request, &mcdx_lock);
1183         if (!mcdx_queue) {
1184                 unregister_blkdev(MAJOR_NR, "mcdx");
1185                 release_region(stuffp->wreg_data, MCDX_IO_SIZE);
1186                 kfree(stuffp);
1187                 put_disk(disk);
1188                 return 1;
1189         }
1190
1191         xtrace(INIT, "init() subscribe irq and i/o\n");
1192         if (request_irq(stuffp->irq, mcdx_intr, IRQF_DISABLED, "mcdx", stuffp)) {
1193                 release_region(stuffp->wreg_data, MCDX_IO_SIZE);
1194                 xwarn("%s=0x%03x,%d: Init failed. Can't get irq (%d).\n",
1195                       MCDX, stuffp->wreg_data, stuffp->irq, stuffp->irq);
1196                 stuffp->irq = 0;
1197                 blk_cleanup_queue(mcdx_queue);
1198                 kfree(stuffp);
1199                 put_disk(disk);
1200                 return 0;
1201         }
1202
1203         xtrace(INIT, "init() get garbage\n");
1204         {
1205                 int i;
1206                 mcdx_delay(stuffp, HZ / 2);
1207                 for (i = 100; i; i--)
1208                         (void) inb(stuffp->rreg_status);
1209         }
1210
1211
1212 #ifdef WE_KNOW_WHY
1213         /* irq 11 -> channel register */
1214         outb(0x50, stuffp->wreg_chn);
1215 #endif
1216
1217         xtrace(INIT, "init() set non dma but irq mode\n");
1218         mcdx_config(stuffp, 1);
1219
1220         stuffp->info.ops = &mcdx_dops;
1221         stuffp->info.speed = 2;
1222         stuffp->info.capacity = 1;
1223         stuffp->info.handle = stuffp;
1224         sprintf(stuffp->info.name, "mcdx%d", drive);
1225         disk->major = MAJOR_NR;
1226         disk->first_minor = drive;
1227         strcpy(disk->disk_name, stuffp->info.name);
1228         disk->fops = &mcdx_bdops;
1229         disk->flags = GENHD_FL_CD;
1230         stuffp->disk = disk;
1231
1232         sprintf(msg, " mcdx: Mitsumi CD-ROM installed at 0x%03x, irq %d."
1233                 " (Firmware version %c %x)\n",
1234                 stuffp->wreg_data, stuffp->irq, version.code, version.ver);
1235         mcdx_stuffp[drive] = stuffp;
1236         xtrace(INIT, "init() mcdx_stuffp[%d] = %p\n", drive, stuffp);
1237         if (register_cdrom(&stuffp->info) != 0) {
1238                 printk("Cannot register Mitsumi CD-ROM!\n");
1239                 free_irq(stuffp->irq, NULL);
1240                 release_region(stuffp->wreg_data, MCDX_IO_SIZE);
1241                 kfree(stuffp);
1242                 put_disk(disk);
1243                 if (unregister_blkdev(MAJOR_NR, "mcdx") != 0)
1244                         xwarn("cleanup() unregister_blkdev() failed\n");
1245                 blk_cleanup_queue(mcdx_queue);
1246                 return 2;
1247         }
1248         disk->private_data = stuffp;
1249         disk->queue = mcdx_queue;
1250         add_disk(disk);
1251         printk(msg);
1252         return 0;
1253 }
1254
1255 static int __init mcdx_init(void)
1256 {
1257         int drive;
1258         xwarn("Version 2.14(hs) \n");
1259
1260         xwarn("$Id: mcdx.c,v 1.21 1997/01/26 07:12:59 davem Exp $\n");
1261
1262         /* zero the pointer array */
1263         for (drive = 0; drive < MCDX_NDRIVES; drive++)
1264                 mcdx_stuffp[drive] = NULL;
1265
1266         /* do the initialisation */
1267         for (drive = 0; drive < MCDX_NDRIVES; drive++) {
1268                 switch (mcdx_init_drive(drive)) {
1269                 case 2:
1270                         return -EIO;
1271                 case 1:
1272                         break;
1273                 }
1274         }
1275         return 0;
1276 }
1277
1278 static int mcdx_transfer(struct s_drive_stuff *stuffp,
1279               char *p, int sector, int nr_sectors)
1280 /*      This seems to do the actually transfer.  But it does more.  It
1281         keeps track of errors occurred and will (if possible) fall back
1282         to single speed on error.
1283         Return: -1 on timeout or other error
1284                         else status byte (as in stuff->st) */
1285 {
1286         int ans;
1287
1288         ans = mcdx_xfer(stuffp, p, sector, nr_sectors);
1289         return ans;
1290 #ifdef FALLBACK
1291         if (-1 == ans)
1292                 stuffp->readerrs++;
1293         else
1294                 return ans;
1295
1296         if (stuffp->readerrs && stuffp->readcmd == READ1X) {
1297                 xwarn("XXX Already reading 1x -- no chance\n");
1298                 return -1;
1299         }
1300
1301         xwarn("XXX Fallback to 1x\n");
1302
1303         stuffp->readcmd = READ1X;
1304         return mcdx_transfer(stuffp, p, sector, nr_sectors);
1305 #endif
1306
1307 }
1308
1309
1310 static int mcdx_xfer(struct s_drive_stuff *stuffp,
1311                      char *p, int sector, int nr_sectors)
1312 /*      This does actually the transfer from the drive.
1313         Return: -1 on timeout or other error
1314                         else status byte (as in stuff->st) */
1315 {
1316         int border;
1317         int done = 0;
1318         long timeout;
1319
1320         if (stuffp->audio) {
1321                 xwarn("Attempt to read from audio CD.\n");
1322                 return -1;
1323         }
1324
1325         if (!stuffp->readcmd) {
1326                 xinfo("Can't transfer from missing disk.\n");
1327                 return -1;
1328         }
1329
1330         while (stuffp->lock) {
1331                 interruptible_sleep_on(&stuffp->lockq);
1332         }
1333
1334         if (stuffp->valid && (sector >= stuffp->pending)
1335             && (sector < stuffp->low_border)) {
1336
1337                 /* All (or at least a part of the sectors requested) seems
1338                    * to be already requested, so we don't need to bother the
1339                    * drive with new requests ...
1340                    * Wait for the drive become idle, but first
1341                    * check for possible occurred errors --- the drive
1342                    * seems to report them asynchronously */
1343
1344
1345                 border = stuffp->high_border < (border =
1346                                                 sector + nr_sectors)
1347                     ? stuffp->high_border : border;
1348
1349                 stuffp->lock = current->pid;
1350
1351                 do {
1352
1353                         while (stuffp->busy) {
1354
1355                                 timeout =
1356                                     interruptible_sleep_on_timeout
1357                                     (&stuffp->busyq, 5 * HZ);
1358
1359                                 if (!stuffp->introk) {
1360                                         xtrace(XFER,
1361                                                "error via interrupt\n");
1362                                 } else if (!timeout) {
1363                                         xtrace(XFER, "timeout\n");
1364                                 } else if (signal_pending(current)) {
1365                                         xtrace(XFER, "signal\n");
1366                                 } else
1367                                         continue;
1368
1369                                 stuffp->lock = 0;
1370                                 stuffp->busy = 0;
1371                                 stuffp->valid = 0;
1372
1373                                 wake_up_interruptible(&stuffp->lockq);
1374                                 xtrace(XFER, "transfer() done (-1)\n");
1375                                 return -1;
1376                         }
1377
1378                         /* check if we need to set the busy flag (as we
1379                          * expect an interrupt */
1380                         stuffp->busy = (3 == (stuffp->pending & 3));
1381
1382                         /* Test if it's the first sector of a block,
1383                          * there we have to skip some bytes as we read raw data */
1384                         if (stuffp->xa && (0 == (stuffp->pending & 3))) {
1385                                 const int HEAD =
1386                                     CD_FRAMESIZE_RAW - CD_XA_TAIL -
1387                                     CD_FRAMESIZE;
1388                                 insb(stuffp->rreg_data, p, HEAD);
1389                         }
1390
1391                         /* now actually read the data */
1392                         insb(stuffp->rreg_data, p, 512);
1393
1394                         /* test if it's the last sector of a block,
1395                          * if so, we have to handle XA special */
1396                         if ((3 == (stuffp->pending & 3)) && stuffp->xa) {
1397                                 char dummy[CD_XA_TAIL];
1398                                 insb(stuffp->rreg_data, &dummy[0], CD_XA_TAIL);
1399                         }
1400
1401                         if (stuffp->pending == sector) {
1402                                 p += 512;
1403                                 done++;
1404                                 sector++;
1405                         }
1406                 } while (++(stuffp->pending) < border);
1407
1408                 stuffp->lock = 0;
1409                 wake_up_interruptible(&stuffp->lockq);
1410
1411         } else {
1412
1413                 /* The requested sector(s) is/are out of the
1414                  * already requested range, so we have to bother the drive
1415                  * with a new request. */
1416
1417                 static unsigned char cmd[] = {
1418                         0,
1419                         0, 0, 0,
1420                         0, 0, 0
1421                 };
1422
1423                 cmd[0] = stuffp->readcmd;
1424
1425                 /* The numbers held in ->pending, ..., should be valid */
1426                 stuffp->valid = 1;
1427                 stuffp->pending = sector & ~3;
1428
1429                 /* do some sanity checks */
1430                 if (stuffp->pending > stuffp->lastsector) {
1431                         xwarn
1432                             ("transfer() sector %d from nirvana requested.\n",
1433                              stuffp->pending);
1434                         stuffp->status = MCDX_ST_EOM;
1435                         stuffp->valid = 0;
1436                         xtrace(XFER, "transfer() done (-1)\n");
1437                         return -1;
1438                 }
1439
1440                 if ((stuffp->low_border = stuffp->pending + DIRECT_SIZE)
1441                     > stuffp->lastsector + 1) {
1442                         xtrace(XFER, "cut low_border\n");
1443                         stuffp->low_border = stuffp->lastsector + 1;
1444                 }
1445                 if ((stuffp->high_border = stuffp->pending + REQUEST_SIZE)
1446                     > stuffp->lastsector + 1) {
1447                         xtrace(XFER, "cut high_border\n");
1448                         stuffp->high_border = stuffp->lastsector + 1;
1449                 }
1450
1451                 {               /* Convert the sector to be requested to MSF format */
1452                         struct cdrom_msf0 pending;
1453                         log2msf(stuffp->pending / 4, &pending);
1454                         cmd[1] = pending.minute;
1455                         cmd[2] = pending.second;
1456                         cmd[3] = pending.frame;
1457                 }
1458
1459                 cmd[6] =
1460                     (unsigned
1461                      char) ((stuffp->high_border - stuffp->pending) / 4);
1462                 xtrace(XFER, "[%2d]\n", cmd[6]);
1463
1464                 stuffp->busy = 1;
1465                 /* Now really issue the request command */
1466                 outsb(stuffp->wreg_data, cmd, sizeof cmd);
1467
1468         }
1469 #ifdef AK2
1470         if (stuffp->int_err) {
1471                 stuffp->valid = 0;
1472                 stuffp->int_err = 0;
1473                 return -1;
1474         }
1475 #endif                          /* AK2 */
1476
1477         stuffp->low_border = (stuffp->low_border +=
1478                               done) <
1479             stuffp->high_border ? stuffp->low_border : stuffp->high_border;
1480
1481         return done;
1482 }
1483
1484
1485 /*      Access to elements of the mcdx_drive_map members */
1486
1487 static unsigned port(int *ip)
1488 {
1489         return ip[0];
1490 }
1491 static int irq(int *ip)
1492 {
1493         return ip[1];
1494 }
1495
1496 /*      Misc number converters */
1497
1498 static unsigned int bcd2uint(unsigned char c)
1499 {
1500         return (c >> 4) * 10 + (c & 0x0f);
1501 }
1502
1503 static unsigned int uint2bcd(unsigned int ival)
1504 {
1505         return ((ival / 10) << 4) | (ival % 10);
1506 }
1507
1508 static void log2msf(unsigned int l, struct cdrom_msf0 *pmsf)
1509 {
1510         l += CD_MSF_OFFSET;
1511         pmsf->minute = uint2bcd(l / 4500), l %= 4500;
1512         pmsf->second = uint2bcd(l / 75);
1513         pmsf->frame = uint2bcd(l % 75);
1514 }
1515
1516 static unsigned int msf2log(const struct cdrom_msf0 *pmsf)
1517 {
1518         return bcd2uint(pmsf->frame)
1519             + bcd2uint(pmsf->second) * 75
1520             + bcd2uint(pmsf->minute) * 4500 - CD_MSF_OFFSET;
1521 }
1522
1523 int mcdx_readtoc(struct s_drive_stuff *stuffp)
1524 /*  Read the toc entries from the CD,
1525  *  Return: -1 on failure, else 0 */
1526 {
1527
1528         if (stuffp->toc) {
1529                 xtrace(READTOC, "ioctl() toc already read\n");
1530                 return 0;
1531         }
1532
1533         xtrace(READTOC, "ioctl() readtoc for %d tracks\n",
1534                stuffp->di.n_last - stuffp->di.n_first + 1);
1535
1536         if (-1 == mcdx_hold(stuffp, 1))
1537                 return -1;
1538
1539         xtrace(READTOC, "ioctl() tocmode\n");
1540         if (-1 == mcdx_setdrivemode(stuffp, TOC, 1))
1541                 return -EIO;
1542
1543         /* all seems to be ok so far ... malloc */
1544         {
1545                 int size;
1546                 size =
1547                     sizeof(struct s_subqcode) * (stuffp->di.n_last -
1548                                                  stuffp->di.n_first + 2);
1549
1550                 xtrace(MALLOC, "ioctl() malloc %d bytes\n", size);
1551                 stuffp->toc = kmalloc(size, GFP_KERNEL);
1552                 if (!stuffp->toc) {
1553                         xwarn("Cannot malloc %d bytes for toc\n", size);
1554                         mcdx_setdrivemode(stuffp, DATA, 1);
1555                         return -EIO;
1556                 }
1557         }
1558
1559         /* now read actually the index */
1560         {
1561                 int trk;
1562                 int retries;
1563
1564                 for (trk = 0;
1565                      trk < (stuffp->di.n_last - stuffp->di.n_first + 1);
1566                      trk++)
1567                         stuffp->toc[trk].index = 0;
1568
1569                 for (retries = 300; retries; retries--) {       /* why 300? */
1570                         struct s_subqcode q;
1571                         unsigned int idx;
1572
1573                         if (-1 == mcdx_requestsubqcode(stuffp, &q, 1)) {
1574                                 mcdx_setdrivemode(stuffp, DATA, 1);
1575                                 return -EIO;
1576                         }
1577
1578                         idx = bcd2uint(q.index);
1579
1580                         if ((idx > 0)
1581                             && (idx <= stuffp->di.n_last)
1582                             && (q.tno == 0)
1583                             && (stuffp->toc[idx - stuffp->di.n_first].
1584                                 index == 0)) {
1585                                 stuffp->toc[idx - stuffp->di.n_first] = q;
1586                                 xtrace(READTOC,
1587                                        "ioctl() toc idx %d (trk %d)\n",
1588                                        idx, trk);
1589                                 trk--;
1590                         }
1591                         if (trk == 0)
1592                                 break;
1593                 }
1594                 memset(&stuffp->
1595                        toc[stuffp->di.n_last - stuffp->di.n_first + 1], 0,
1596                        sizeof(stuffp->toc[0]));
1597                 stuffp->toc[stuffp->di.n_last - stuffp->di.n_first +
1598                             1].dt = stuffp->di.msf_leadout;
1599         }
1600
1601         /* unset toc mode */
1602         xtrace(READTOC, "ioctl() undo toc mode\n");
1603         if (-1 == mcdx_setdrivemode(stuffp, DATA, 2))
1604                 return -EIO;
1605
1606 #if MCDX_DEBUG && READTOC
1607         {
1608                 int trk;
1609                 for (trk = 0;
1610                      trk < (stuffp->di.n_last - stuffp->di.n_first + 2);
1611                      trk++)
1612                         xtrace(READTOC, "ioctl() %d readtoc %02x %02x %02x"
1613                                "  %02x:%02x.%02x  %02x:%02x.%02x\n",
1614                                trk + stuffp->di.n_first,
1615                                stuffp->toc[trk].control,
1616                                stuffp->toc[trk].tno,
1617                                stuffp->toc[trk].index,
1618                                stuffp->toc[trk].tt.minute,
1619                                stuffp->toc[trk].tt.second,
1620                                stuffp->toc[trk].tt.frame,
1621                                stuffp->toc[trk].dt.minute,
1622                                stuffp->toc[trk].dt.second,
1623                                stuffp->toc[trk].dt.frame);
1624         }
1625 #endif
1626
1627         return 0;
1628 }
1629
1630 static int
1631 mcdx_playmsf(struct s_drive_stuff *stuffp, const struct cdrom_msf *msf)
1632 {
1633         unsigned char cmd[7] = {
1634                 0, 0, 0, 0, 0, 0, 0
1635         };
1636
1637         if (!stuffp->readcmd) {
1638                 xinfo("Can't play from missing disk.\n");
1639                 return -1;
1640         }
1641
1642         cmd[0] = stuffp->playcmd;
1643
1644         cmd[1] = msf->cdmsf_min0;
1645         cmd[2] = msf->cdmsf_sec0;
1646         cmd[3] = msf->cdmsf_frame0;
1647         cmd[4] = msf->cdmsf_min1;
1648         cmd[5] = msf->cdmsf_sec1;
1649         cmd[6] = msf->cdmsf_frame1;
1650
1651         xtrace(PLAYMSF, "ioctl(): play %x "
1652                "%02x:%02x:%02x -- %02x:%02x:%02x\n",
1653                cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6]);
1654
1655         outsb(stuffp->wreg_data, cmd, sizeof cmd);
1656
1657         if (-1 == mcdx_getval(stuffp, 3 * HZ, 0, NULL)) {
1658                 xwarn("playmsf() timeout\n");
1659                 return -1;
1660         }
1661
1662         stuffp->audiostatus = CDROM_AUDIO_PLAY;
1663         return 0;
1664 }
1665
1666 static int
1667 mcdx_playtrk(struct s_drive_stuff *stuffp, const struct cdrom_ti *ti)
1668 {
1669         struct s_subqcode *p;
1670         struct cdrom_msf msf;
1671
1672         if (-1 == mcdx_readtoc(stuffp))
1673                 return -1;
1674
1675         if (ti)
1676                 p = &stuffp->toc[ti->cdti_trk0 - stuffp->di.n_first];
1677         else
1678                 p = &stuffp->start;
1679
1680         msf.cdmsf_min0 = p->dt.minute;
1681         msf.cdmsf_sec0 = p->dt.second;
1682         msf.cdmsf_frame0 = p->dt.frame;
1683
1684         if (ti) {
1685                 p = &stuffp->toc[ti->cdti_trk1 - stuffp->di.n_first + 1];
1686                 stuffp->stop = *p;
1687         } else
1688                 p = &stuffp->stop;
1689
1690         msf.cdmsf_min1 = p->dt.minute;
1691         msf.cdmsf_sec1 = p->dt.second;
1692         msf.cdmsf_frame1 = p->dt.frame;
1693
1694         return mcdx_playmsf(stuffp, &msf);
1695 }
1696
1697
1698 /* Drive functions ************************************************/
1699
1700 static int mcdx_tray_move(struct cdrom_device_info *cdi, int position)
1701 {
1702         struct s_drive_stuff *stuffp = cdi->handle;
1703
1704         if (!stuffp->present)
1705                 return -ENXIO;
1706         if (!(stuffp->present & DOOR))
1707                 return -ENOSYS;
1708
1709         if (position)           /* 1: eject */
1710                 return mcdx_talk(stuffp, "\xf6", 1, NULL, 1, 5 * HZ, 3);
1711         else                    /* 0: close */
1712                 return mcdx_talk(stuffp, "\xf8", 1, NULL, 1, 5 * HZ, 3);
1713         return 1;
1714 }
1715
1716 static int mcdx_stop(struct s_drive_stuff *stuffp, int tries)
1717 {
1718         return mcdx_talk(stuffp, "\xf0", 1, NULL, 1, 2 * HZ, tries);
1719 }
1720
1721 static int mcdx_hold(struct s_drive_stuff *stuffp, int tries)
1722 {
1723         return mcdx_talk(stuffp, "\x70", 1, NULL, 1, 2 * HZ, tries);
1724 }
1725
1726 static int mcdx_requestsubqcode(struct s_drive_stuff *stuffp,
1727                      struct s_subqcode *sub, int tries)
1728 {
1729         char buf[11];
1730         int ans;
1731
1732         if (-1 == (ans = mcdx_talk(stuffp, "\x20", 1, buf, sizeof(buf),
1733                                    2 * HZ, tries)))
1734                 return -1;
1735         sub->control = buf[1];
1736         sub->tno = buf[2];
1737         sub->index = buf[3];
1738         sub->tt.minute = buf[4];
1739         sub->tt.second = buf[5];
1740         sub->tt.frame = buf[6];
1741         sub->dt.minute = buf[8];
1742         sub->dt.second = buf[9];
1743         sub->dt.frame = buf[10];
1744
1745         return ans;
1746 }
1747
1748 static int mcdx_requestmultidiskinfo(struct s_drive_stuff *stuffp,
1749                           struct s_multi *multi, int tries)
1750 {
1751         char buf[5];
1752         int ans;
1753
1754         if (stuffp->present & MULTI) {
1755                 ans =
1756                     mcdx_talk(stuffp, "\x11", 1, buf, sizeof(buf), 2 * HZ,
1757                               tries);
1758                 multi->multi = buf[1];
1759                 multi->msf_last.minute = buf[2];
1760                 multi->msf_last.second = buf[3];
1761                 multi->msf_last.frame = buf[4];
1762                 return ans;
1763         } else {
1764                 multi->multi = 0;
1765                 return 0;
1766         }
1767 }
1768
1769 static int mcdx_requesttocdata(struct s_drive_stuff *stuffp, struct s_diskinfo *info,
1770                     int tries)
1771 {
1772         char buf[9];
1773         int ans;
1774         ans =
1775             mcdx_talk(stuffp, "\x10", 1, buf, sizeof(buf), 2 * HZ, tries);
1776         if (ans == -1) {
1777                 info->n_first = 0;
1778                 info->n_last = 0;
1779         } else {
1780                 info->n_first = bcd2uint(buf[1]);
1781                 info->n_last = bcd2uint(buf[2]);
1782                 info->msf_leadout.minute = buf[3];
1783                 info->msf_leadout.second = buf[4];
1784                 info->msf_leadout.frame = buf[5];
1785                 info->msf_first.minute = buf[6];
1786                 info->msf_first.second = buf[7];
1787                 info->msf_first.frame = buf[8];
1788         }
1789         return ans;
1790 }
1791
1792 static int mcdx_setdrivemode(struct s_drive_stuff *stuffp, enum drivemodes mode,
1793                   int tries)
1794 {
1795         char cmd[2];
1796         int ans;
1797
1798         xtrace(HW, "setdrivemode() %d\n", mode);
1799
1800         if (-1 == (ans = mcdx_talk(stuffp, "\xc2", 1, cmd, sizeof(cmd), 5 * HZ, tries)))
1801                 return -1;
1802
1803         switch (mode) {
1804         case TOC:
1805                 cmd[1] |= 0x04;
1806                 break;
1807         case DATA:
1808                 cmd[1] &= ~0x04;
1809                 break;
1810         case RAW:
1811                 cmd[1] |= 0x40;
1812                 break;
1813         case COOKED:
1814                 cmd[1] &= ~0x40;
1815                 break;
1816         default:
1817                 break;
1818         }
1819         cmd[0] = 0x50;
1820         return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
1821 }
1822
1823 static int mcdx_setdatamode(struct s_drive_stuff *stuffp, enum datamodes mode,
1824                  int tries)
1825 {
1826         unsigned char cmd[2] = { 0xa0 };
1827         xtrace(HW, "setdatamode() %d\n", mode);
1828         switch (mode) {
1829         case MODE0:
1830                 cmd[1] = 0x00;
1831                 break;
1832         case MODE1:
1833                 cmd[1] = 0x01;
1834                 break;
1835         case MODE2:
1836                 cmd[1] = 0x02;
1837                 break;
1838         default:
1839                 return -EINVAL;
1840         }
1841         return mcdx_talk(stuffp, cmd, 2, NULL, 1, 5 * HZ, tries);
1842 }
1843
1844 static int mcdx_config(struct s_drive_stuff *stuffp, int tries)
1845 {
1846         char cmd[4];
1847
1848         xtrace(HW, "config()\n");
1849
1850         cmd[0] = 0x90;
1851
1852         cmd[1] = 0x10;          /* irq enable */
1853         cmd[2] = 0x05;          /* pre, err irq enable */
1854
1855         if (-1 == mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries))
1856                 return -1;
1857
1858         cmd[1] = 0x02;          /* dma select */
1859         cmd[2] = 0x00;          /* no dma */
1860
1861         return mcdx_talk(stuffp, cmd, 3, NULL, 1, 1 * HZ, tries);
1862 }
1863
1864 static int mcdx_requestversion(struct s_drive_stuff *stuffp, struct s_version *ver,
1865                     int tries)
1866 {
1867         char buf[3];
1868         int ans;
1869
1870         if (-1 == (ans = mcdx_talk(stuffp, "\xdc",
1871                                    1, buf, sizeof(buf), 2 * HZ, tries)))
1872                 return ans;
1873
1874         ver->code = buf[1];
1875         ver->ver = buf[2];
1876
1877         return ans;
1878 }
1879
1880 static int mcdx_reset(struct s_drive_stuff *stuffp, enum resetmodes mode, int tries)
1881 {
1882         if (mode == HARD) {
1883                 outb(0, stuffp->wreg_chn);      /* no dma, no irq -> hardware */
1884                 outb(0, stuffp->wreg_reset);    /* hw reset */
1885                 return 0;
1886         } else
1887                 return mcdx_talk(stuffp, "\x60", 1, NULL, 1, 5 * HZ, tries);
1888 }
1889
1890 static int mcdx_lockdoor(struct cdrom_device_info *cdi, int lock)
1891 {
1892         struct s_drive_stuff *stuffp = cdi->handle;
1893         char cmd[2] = { 0xfe };
1894
1895         if (!(stuffp->present & DOOR))
1896                 return -ENOSYS;
1897         if (stuffp->present & DOOR) {
1898                 cmd[1] = lock ? 0x01 : 0x00;
1899                 return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 1, 5 * HZ, 3);
1900         } else
1901                 return 0;
1902 }
1903
1904 static int mcdx_getstatus(struct s_drive_stuff *stuffp, int tries)
1905 {
1906         return mcdx_talk(stuffp, "\x40", 1, NULL, 1, 5 * HZ, tries);
1907 }
1908
1909 static int
1910 mcdx_getval(struct s_drive_stuff *stuffp, int to, int delay, char *buf)
1911 {
1912         unsigned long timeout = to + jiffies;
1913         char c;
1914
1915         if (!buf)
1916                 buf = &c;
1917
1918         while (inb(stuffp->rreg_status) & MCDX_RBIT_STEN) {
1919                 if (time_after(jiffies, timeout))
1920                         return -1;
1921                 mcdx_delay(stuffp, delay);
1922         }
1923
1924         *buf = (unsigned char) inb(stuffp->rreg_data) & 0xff;
1925
1926         return 0;
1927 }
1928
1929 static int mcdx_setattentuator(struct s_drive_stuff *stuffp,
1930                     struct cdrom_volctrl *vol, int tries)
1931 {
1932         char cmd[5];
1933         cmd[0] = 0xae;
1934         cmd[1] = vol->channel0;
1935         cmd[2] = 0;
1936         cmd[3] = vol->channel1;
1937         cmd[4] = 0;
1938
1939         return mcdx_talk(stuffp, cmd, sizeof(cmd), NULL, 5, 200, tries);
1940 }
1941
1942 MODULE_LICENSE("GPL");
1943 MODULE_ALIAS_BLOCKDEV_MAJOR(MITSUMI_X_CDROM_MAJOR);