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