2 linux/kernel/blk_drv/mcd.c - Mitsumi CDROM driver
4 Copyright (C) 1992 Martin Harriss
6 martin@bdsi.com (no longer valid - where are you now, Martin?)
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 0.1 First attempt - internal use only
25 0.2 Cleaned up delays and use of timer - alpha release
26 0.3 Audio support added
27 0.3.1 Changes for mitsumi CRMC LU005S march version
28 (stud11@cc4.kuleuven.ac.be)
29 0.3.2 bug fixes to the ioctls and merged with ALPHA0.99-pl12
30 (Jon Tombs <jon@robots.ox.ac.uk>)
31 0.3.3 Added more #defines and mcd_setup()
32 (Jon Tombs <jon@gtex02.us.es>)
34 October 1993 Bernd Huebner and Ruediger Helsch, Unifix Software GmbH,
35 Braunschweig, Germany: rework to speed up data read operation.
36 Also enabled definition of irq and address from bootstrap, using the
38 November 93 added code for FX001 S,D (single & double speed).
39 February 94 added code for broken M 5/6 series of 16-bit single speed.
43 Added support for loadable MODULEs, so mcd can now also be loaded by
44 insmod and removed by rmmod during runtime.
45 Werner Zimmermann (zimmerma@rz.fht-esslingen.de), Mar. 26, 95
48 I added code for FX001 D to drop from double speed to single speed
49 when encountering errors... this helps with some "problematic" CD's
50 that are supposedly "OUT OF TOLERANCE" (but are really shitty presses!)
51 severely scratched, or possibly slightly warped! I have noticed that
52 the Mitsumi 2x/4x drives are just less tolerant and the firmware is
53 not smart enough to drop speed, so let's just kludge it with software!
54 ****** THE 4X SPEED MITSUMI DRIVES HAVE THE SAME PROBLEM!!!!!! ******
55 Anyone want to "DONATE" one to me?! ;) I hear sometimes they are
57 ** HINT... HINT... TAKE NOTES MITSUMI This could save some hassles with
58 certain "large" CD's that have data on the outside edge in your
59 DOS DRIVERS .... Accuracy counts... speed is secondary ;)
60 17 June 95 Modifications By Andrew J. Kroll <ag784@freenet.buffalo.edu>
61 07 July 1995 Modifications by Andrew J. Kroll
63 Bjorn Ekwall <bj0rn@blox.se> added unregister_blkdev to mcd_init()
65 Michael K. Johnson <johnsonm@redhat.com> added retries on open
66 for slow drives which take a while to recognize that they contain
69 November 1997 -- ported to the Uniform CD-ROM driver by Erik Andersen.
70 March 1999 -- made io base and irq CONFIG_ options (Tigran Aivazian).
72 November 1999 -- Make kernel-parameter implementation work with 2.3.x
73 Removed init_module & cleanup_module in favor of
74 module_init & module_exit.
75 Torben Mathiasen <tmm@image.dk>
80 #include <linux/module.h>
82 #include <linux/errno.h>
83 #include <linux/signal.h>
84 #include <linux/sched.h>
86 #include <linux/timer.h>
88 #include <linux/kernel.h>
89 #include <linux/devfs_fs_kernel.h>
90 #include <linux/cdrom.h>
91 #include <linux/ioport.h>
92 #include <linux/string.h>
93 #include <linux/delay.h>
94 #include <linux/init.h>
95 #include <linux/config.h>
97 /* #define REALLY_SLOW_IO */
98 #include <asm/system.h>
100 #include <asm/uaccess.h>
102 #define MAJOR_NR MITSUMI_CDROM_MAJOR
103 #include <linux/blk.h>
105 #define mcd_port mcd /* for compatible parameter passing with "insmod" */
108 static int mcd_blocksizes
[1] = { 0, };
111 /* I added A flag to drop to 1x speed if too many errors 0 = 1X ; 1 = 2X */
112 static int mcdDouble
= 0;
114 /* How many sectors to hold at 1x speed counter */
115 static int mcd1xhold
= 0;
117 /* Is the drive connected properly and responding?? */
118 static int mcdPresent
= 0;
121 #define TEST1 /* <int-..> */
122 #define TEST2 /* do_mcd_req */
123 #define TEST3 */ /* MCD_S_state */
124 #define TEST4 /* QUICK_LOOP-counter */
125 #define TEST5 */ /* port(1) state */
129 #define QUICK_LOOP_DELAY udelay(45) /* use udelay */
130 #define QUICK_LOOP_COUNT 20
132 #define QUICK_LOOP_DELAY
133 #define QUICK_LOOP_COUNT 140 /* better wait constant time */
135 /* #define DOUBLE_QUICK_ONLY */
137 #define CURRENT_VALID \
138 (!QUEUE_EMPTY && MAJOR(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \
139 && CURRENT -> sector != -1)
141 #define MFL_STATUSorDATA (MFL_STATUS | MFL_DATA)
142 #define MCD_BUF_SIZ 16
143 static volatile int mcd_transfer_is_active
;
144 static char mcd_buf
[2048*MCD_BUF_SIZ
]; /* buffer for block size conversion */
145 static volatile int mcd_buf_bn
[MCD_BUF_SIZ
], mcd_next_bn
;
146 static volatile int mcd_buf_in
, mcd_buf_out
= -1;
147 static volatile int mcd_error
;
148 static int mcd_open_count
;
156 MCD_S_STOPPING
/* 6 */
158 static volatile enum mcd_state_e mcd_state
= MCD_S_IDLE
;
159 static int mcd_mode
= -1;
160 static int MCMD_DATA_READ
= MCMD_PLAY_READ
;
161 #define READ_TIMEOUT 3000
162 #define WORK_AROUND_MITSUMI_BUG_92
163 #define WORK_AROUND_MITSUMI_BUG_93
164 #ifdef WORK_AROUND_MITSUMI_BUG_93
165 int mitsumi_bug_93_wait
= 0;
166 #endif /* WORK_AROUND_MITSUMI_BUG_93 */
168 static short mcd_port
= CONFIG_MCD_BASE
; /* used as "mcd" by "insmod" */
169 static int mcd_irq
= CONFIG_MCD_IRQ
; /* must directly follow mcd_port */
170 MODULE_PARM(mcd
, "1-2i");
172 static int McdTimeout
, McdTries
;
173 static DECLARE_WAIT_QUEUE_HEAD(mcd_waitq
);
175 static struct mcd_DiskInfo DiskInfo
;
176 static struct mcd_Toc Toc
[MAX_TRACKS
];
177 static struct mcd_Play_msf mcd_Play
;
179 static int audioStatus
;
180 static char mcdDiskChanged
;
181 static char tocUpToDate
;
182 static char mcdVersion
;
184 static void mcd_transfer(void);
185 static void mcd_poll(void);
186 static void mcd_invalidate_buffers(void);
187 static void hsg2msf(long hsg
, struct msf
*msf
);
188 static void bin2bcd(unsigned char *p
);
189 static int bcd2bin(unsigned char bcd
);
190 static int mcdStatus(void);
191 static void sendMcdCmd(int cmd
, struct mcd_Play_msf
*params
);
192 static int getMcdStatus(int timeout
);
193 static int GetQChannelInfo(struct mcd_Toc
*qp
);
194 static int updateToc(void);
195 static int GetDiskInfo(void);
196 static int GetToc(void);
197 static int getValue(unsigned char *result
);
198 static int mcd_open(struct cdrom_device_info
* cdi
, int purpose
);
199 static void mcd_release(struct cdrom_device_info
* cdi
);
200 static int mcd_media_changed(struct cdrom_device_info
* cdi
, int disc_nr
);
201 static int mcd_tray_move(struct cdrom_device_info
* cdi
, int position
);
202 int mcd_audio_ioctl(struct cdrom_device_info
* cdi
, unsigned int cmd
,
204 int mcd_drive_status(struct cdrom_device_info
* cdi
, int slot_nr
);
206 static struct cdrom_device_ops mcd_dops
= {
208 mcd_release
, /* release */
209 mcd_drive_status
, /* drive status */
210 //NULL, /* drive status */
211 mcd_media_changed
, /* media changed */
212 mcd_tray_move
, /* tray move */
213 NULL
, /* lock door */
214 NULL
, /* select speed */
215 NULL
, /* select disc */
216 NULL
, /* get last session */
217 NULL
, /* get universal product code */
218 NULL
, /* hard reset */
219 mcd_audio_ioctl
, /* audio ioctl */
220 NULL
, /* device-specific ioctl */
221 CDC_OPEN_TRAY
| CDC_MEDIA_CHANGED
| CDC_PLAY_AUDIO
222 | CDC_DRIVE_STATUS
, /* capability */
223 0, /* number of minor devices */
226 static struct cdrom_device_info mcd_info
= {
227 &mcd_dops
, /* device operations */
232 2, /* maximum speed */
233 1, /* number of discs */
234 0, /* options, not owned */
235 0, /* mc_flags, not owned */
236 0, /* use count, not owned */
237 "mcd", /* name of the device type */
241 static int __init
mcd_setup(char *str
)
245 (void)get_options(str
, ARRAY_SIZE(ints
), ints
);
251 #ifdef WORK_AROUND_MITSUMI_BUG_93
253 mitsumi_bug_93_wait
= ints
[3];
254 #endif /* WORK_AROUND_MITSUMI_BUG_93 */
259 __setup("mcd=", mcd_setup
);
263 static int mcd_media_changed(struct cdrom_device_info
* cdi
, int disc_nr
)
268 #if 1 /* the below is not reliable */
273 printk("mcd: Mitsumi CD-ROM request error: invalid device.\n");
277 retval
= mcdDiskChanged
;
285 * Do a 'get status' command and get the result. Only use from the top half
286 * because it calls 'getMcdStatus' which sleeps.
294 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
296 outb(MCMD_GET_STATUS
, MCDPORT(0)); /* send get-status cmd */
298 st
= getMcdStatus(MCD_STATUS_DELAY
);
308 * Send a 'Play' command and get the status. Use only from the top half.
312 mcdPlay(struct mcd_Play_msf
*arg
)
316 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
318 sendMcdCmd(MCMD_PLAY_READ
, arg
);
319 st
= getMcdStatus(2 * MCD_STATUS_DELAY
);
329 mcd_tray_move(struct cdrom_device_info
* cdi
, int position
)
334 /* all drives can at least stop! */
335 if (audioStatus
== CDROM_AUDIO_PLAY
) {
336 outb(MCMD_STOP
, MCDPORT(0));
337 i
= getMcdStatus(MCD_STATUS_DELAY
);
340 audioStatus
= CDROM_AUDIO_NO_STATUS
;
342 outb(MCMD_EJECT
, MCDPORT(0));
344 * the status (i) shows failure on all but the FX drives.
345 * But nothing we can do about that in software!
346 * So just read the status and forget it. - Jon.
348 i
= getMcdStatus(MCD_STATUS_DELAY
);
356 msf2hsg(struct msf
*mp
)
358 return bcd2bin(mp
-> frame
)
359 + bcd2bin(mp
-> sec
) * 75
360 + bcd2bin(mp
-> min
) * 4500
365 int mcd_audio_ioctl(struct cdrom_device_info
* cdi
, unsigned int cmd
,
369 struct mcd_Toc qInfo
;
371 struct cdrom_tochdr
*tocHdr
;
372 struct cdrom_msf
*msf
;
373 struct cdrom_subchnl
*subchnl
;
374 struct cdrom_tocentry
*entry
;
375 struct mcd_Toc
*tocPtr
;
376 struct cdrom_volctrl
*volctrl
;
386 return i
; /* error reading TOC */
391 case CDROMSTART
: /* Spin up the drive */
392 /* Don't think we can do this. Even if we could,
393 * I think the drive times out and stops after a while
394 * anyway. For now, ignore it.
399 case CDROMSTOP
: /* Spin down the drive */
400 outb(MCMD_STOP
, MCDPORT(0));
401 i
= getMcdStatus(MCD_STATUS_DELAY
);
403 /* should we do anything if it fails? */
405 audioStatus
= CDROM_AUDIO_NO_STATUS
;
408 case CDROMPAUSE
: /* Pause the drive */
409 if (audioStatus
!= CDROM_AUDIO_PLAY
)
412 outb(MCMD_STOP
, MCDPORT(0));
413 i
= getMcdStatus(MCD_STATUS_DELAY
);
415 if (GetQChannelInfo(&qInfo
) < 0)
417 /* didn't get q channel info */
419 audioStatus
= CDROM_AUDIO_NO_STATUS
;
423 mcd_Play
.start
= qInfo
.diskTime
; /* remember restart point */
425 audioStatus
= CDROM_AUDIO_PAUSED
;
428 case CDROMRESUME
: /* Play it again, Sam */
429 if (audioStatus
!= CDROM_AUDIO_PAUSED
)
432 /* restart the drive at the saved position. */
434 i
= mcdPlay(&mcd_Play
);
437 audioStatus
= CDROM_AUDIO_ERROR
;
441 audioStatus
= CDROM_AUDIO_PLAY
;
444 case CDROMPLAYTRKIND
: /* Play a track. This currently ignores index. */
446 ti
=(struct cdrom_ti
*) arg
;
448 if (ti
->cdti_trk0
< DiskInfo
.first
449 || ti
->cdti_trk0
> DiskInfo
.last
450 || ti
->cdti_trk1
< ti
->cdti_trk0
)
455 if (ti
->cdti_trk1
> DiskInfo
.last
)
456 ti
->cdti_trk1
= DiskInfo
.last
;
458 mcd_Play
.start
= Toc
[ti
->cdti_trk0
].diskTime
;
459 mcd_Play
.end
= Toc
[ti
->cdti_trk1
+ 1].diskTime
;
462 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
463 mcd_Play
.start
.min
, mcd_Play
.start
.sec
, mcd_Play
.start
.frame
,
464 mcd_Play
.end
.min
, mcd_Play
.end
.sec
, mcd_Play
.end
.frame
);
467 i
= mcdPlay(&mcd_Play
);
470 audioStatus
= CDROM_AUDIO_ERROR
;
474 audioStatus
= CDROM_AUDIO_PLAY
;
477 case CDROMPLAYMSF
: /* Play starting at the given MSF address. */
479 if (audioStatus
== CDROM_AUDIO_PLAY
) {
480 outb(MCMD_STOP
, MCDPORT(0));
481 i
= getMcdStatus(MCD_STATUS_DELAY
);
482 audioStatus
= CDROM_AUDIO_NO_STATUS
;
485 msf
=(struct cdrom_msf
*) arg
;
489 bin2bcd(&msf
->cdmsf_min0
);
490 bin2bcd(&msf
->cdmsf_sec0
);
491 bin2bcd(&msf
->cdmsf_frame0
);
492 bin2bcd(&msf
->cdmsf_min1
);
493 bin2bcd(&msf
->cdmsf_sec1
);
494 bin2bcd(&msf
->cdmsf_frame1
);
496 mcd_Play
.start
.min
= msf
->cdmsf_min0
;
497 mcd_Play
.start
.sec
= msf
->cdmsf_sec0
;
498 mcd_Play
.start
.frame
= msf
->cdmsf_frame0
;
499 mcd_Play
.end
.min
= msf
->cdmsf_min1
;
500 mcd_Play
.end
.sec
= msf
->cdmsf_sec1
;
501 mcd_Play
.end
.frame
= msf
->cdmsf_frame1
;
504 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
505 mcd_Play
.start
.min
, mcd_Play
.start
.sec
, mcd_Play
.start
.frame
,
506 mcd_Play
.end
.min
, mcd_Play
.end
.sec
, mcd_Play
.end
.frame
);
509 i
= mcdPlay(&mcd_Play
);
512 audioStatus
= CDROM_AUDIO_ERROR
;
516 audioStatus
= CDROM_AUDIO_PLAY
;
519 case CDROMREADTOCHDR
: /* Read the table of contents header */
520 tocHdr
=(struct cdrom_tochdr
*) arg
;
521 tocHdr
->cdth_trk0
= DiskInfo
.first
;
522 tocHdr
->cdth_trk1
= DiskInfo
.last
;
525 case CDROMREADTOCENTRY
: /* Read an entry in the table of contents */
526 entry
=(struct cdrom_tocentry
*) arg
;
527 if (entry
->cdte_track
== CDROM_LEADOUT
)
528 tocPtr
= &Toc
[DiskInfo
.last
- DiskInfo
.first
+ 1];
530 else if (entry
->cdte_track
> DiskInfo
.last
531 || entry
->cdte_track
< DiskInfo
.first
)
535 tocPtr
= &Toc
[entry
->cdte_track
];
537 entry
->cdte_adr
= tocPtr
-> ctrl_addr
;
538 entry
->cdte_ctrl
= tocPtr
-> ctrl_addr
>> 4;
540 if (entry
->cdte_format
== CDROM_LBA
)
541 entry
->cdte_addr
.lba
= msf2hsg(&tocPtr
-> diskTime
);
543 else if (entry
->cdte_format
== CDROM_MSF
)
545 entry
->cdte_addr
.msf
.minute
= bcd2bin(tocPtr
-> diskTime
.min
);
546 entry
->cdte_addr
.msf
.second
= bcd2bin(tocPtr
-> diskTime
.sec
);
547 entry
->cdte_addr
.msf
.frame
= bcd2bin(tocPtr
-> diskTime
.frame
);
555 case CDROMSUBCHNL
: /* Get subchannel info */
557 subchnl
=(struct cdrom_subchnl
*) arg
;
558 if (GetQChannelInfo(&qInfo
) < 0)
561 subchnl
->cdsc_audiostatus
= audioStatus
;
562 subchnl
->cdsc_adr
= qInfo
.ctrl_addr
;
563 subchnl
->cdsc_ctrl
= qInfo
.ctrl_addr
>> 4;
564 subchnl
->cdsc_trk
= bcd2bin(qInfo
.track
);
565 subchnl
->cdsc_ind
= bcd2bin(qInfo
.pointIndex
);
566 subchnl
->cdsc_absaddr
.msf
.minute
= bcd2bin(qInfo
.diskTime
.min
);
567 subchnl
->cdsc_absaddr
.msf
.second
= bcd2bin(qInfo
.diskTime
.sec
);
568 subchnl
->cdsc_absaddr
.msf
.frame
= bcd2bin(qInfo
.diskTime
.frame
);
569 subchnl
->cdsc_reladdr
.msf
.minute
= bcd2bin(qInfo
.trackTime
.min
);
570 subchnl
->cdsc_reladdr
.msf
.second
= bcd2bin(qInfo
.trackTime
.sec
);
571 subchnl
->cdsc_reladdr
.msf
.frame
= bcd2bin(qInfo
.trackTime
.frame
);
574 case CDROMVOLCTRL
: /* Volume control */
575 volctrl
=(struct cdrom_volctrl
*) arg
;
576 outb(MCMD_SET_VOLUME
, MCDPORT(0));
577 outb(volctrl
->channel0
, MCDPORT(0));
578 outb(255, MCDPORT(0));
579 outb(volctrl
->channel1
, MCDPORT(0));
580 outb(255, MCDPORT(0));
582 i
= getMcdStatus(MCD_STATUS_DELAY
);
603 * Take care of the different block sizes between cdrom and Linux.
604 * When Linux gets variable block sizes this will probably go away.
611 while (CURRENT
-> nr_sectors
) {
612 int bn
= CURRENT
-> sector
/ 4;
614 for (i
= 0; i
< MCD_BUF_SIZ
&& mcd_buf_bn
[i
] != bn
; ++i
)
616 if (i
< MCD_BUF_SIZ
) {
617 int offs
= (i
* 4 + (CURRENT
-> sector
& 3)) * 512;
618 int nr_sectors
= 4 - (CURRENT
-> sector
& 3);
619 if (mcd_buf_out
!= i
) {
621 if (mcd_buf_bn
[i
] != bn
) {
626 if (nr_sectors
> CURRENT
-> nr_sectors
)
627 nr_sectors
= CURRENT
-> nr_sectors
;
628 memcpy(CURRENT
-> buffer
, mcd_buf
+ offs
, nr_sectors
* 512);
629 CURRENT
-> nr_sectors
-= nr_sectors
;
630 CURRENT
-> sector
+= nr_sectors
;
631 CURRENT
-> buffer
+= nr_sectors
* 512;
642 * We only seem to get interrupts after an error.
643 * Just take the interrupt and clear out the status reg.
647 mcd_interrupt(int irq
, void *dev_id
, struct pt_regs
* regs
)
651 st
= inb(MCDPORT(1)) & 0xFF;
653 printk("<int1-%02X>", st
);
655 if (!(st
& MFL_STATUS
))
657 st
= inb(MCDPORT(0)) & 0xFF;
659 printk("<int0-%02X>", st
);
661 if ((st
& 0xFF) != 0xFF)
662 mcd_error
= st
? st
& 0xFF : -1;
668 do_mcd_request(request_queue_t
* q
)
671 printk(" do_mcd_request(%ld+%ld)\n", CURRENT
-> sector
, CURRENT
-> nr_sectors
);
673 mcd_transfer_is_active
= 1;
674 while (CURRENT_VALID
) {
676 if (!buffer_locked(CURRENT
->bh
))
677 panic(DEVICE_NAME
": block not locked");
680 if (CURRENT
-> nr_sectors
== 0) {
683 mcd_buf_out
= -1; /* Want to read a block not in buffer */
684 if (mcd_state
== MCD_S_IDLE
) {
686 if (updateToc() < 0) {
687 while (CURRENT_VALID
)
692 mcd_state
= MCD_S_START
;
694 SET_TIMER(mcd_poll
, 1);
699 mcd_transfer_is_active
= 0;
701 printk(" do_mcd_request ends\n");
715 if (mcd_error
& 0xA5)
717 printk("mcd: I/O error 0x%02x", mcd_error
);
718 if (mcd_error
& 0x80)
719 printk(" (Door open)");
720 if (mcd_error
& 0x20)
721 printk(" (Disk changed)");
722 if (mcd_error
& 0x04)
724 printk(" (Read error)"); /* Bitch about the problem. */
726 /* Time to get fancy! If at 2x speed and 1 error, drop to 1x speed! */
727 /* Interesting how it STAYS at MCD_RETRY_ATTEMPTS on first error! */
728 /* But I find that rather HANDY!!! */
729 /* Neat! it REALLY WORKS on those LOW QUALITY CD's!!! Smile! :) */
732 /* Slap the CD down to single speed! */
733 if (mcdDouble
== 1 && McdTries
== MCD_RETRY_ATTEMPTS
&& MCMD_DATA_READ
== MCMD_2X_READ
)
735 MCMD_DATA_READ
= MCMD_PLAY_READ
; /* Uhhh, Ummmm, muhuh-huh! */
736 mcd1xhold
= SINGLE_HOLD_SECTORS
; /* Hey Beavis! */
737 printk(" Speed now 1x"); /* Pull my finger! */
741 mcd_invalidate_buffers();
742 #ifdef WARN_IF_READ_FAILURE
743 if (McdTries
== MCD_RETRY_ATTEMPTS
)
744 printk("mcd: read of block %d failed\n", mcd_next_bn
);
748 /* Nuts! This cd is ready for recycling! */
749 /* When WAS the last time YOU cleaned it CORRECTLY?! */
750 printk("mcd: read of block %d failed, giving up\n", mcd_next_bn
);
751 if (mcd_transfer_is_active
)
758 McdTries
= MCD_RETRY_ATTEMPTS
;
762 mcd_state
= MCD_S_STOP
;
764 /* Switch back to Double speed if enough GOOD sectors were read! */
766 /* Are we a double speed with a crappy CD?! */
767 if (mcdDouble
== 1 && McdTries
== MCD_RETRY_ATTEMPTS
&& MCMD_DATA_READ
== MCMD_PLAY_READ
)
769 /* We ARE a double speed and we ARE bitching! */
770 if (mcd1xhold
== 0) /* Okay, Like are we STILL at single speed? */
771 { /* We need to switch back to double speed now... */
772 MCMD_DATA_READ
= MCMD_2X_READ
; /* Uhhh... BACK You GO! */
773 printk("mcd: Switching back to 2X speed!\n"); /* Tell 'em! */
775 else mcd1xhold
--; /* No?! Count down the good reads some more... */
776 /* and try, try again! */
788 printk("MCD_S_IDLE\n");
796 printk("MCD_S_START\n");
799 outb(MCMD_GET_STATUS
, MCDPORT(0));
800 mcd_state
= mcd_mode
== 1 ? MCD_S_READ
: MCD_S_MODE
;
808 printk("MCD_S_MODE\n");
811 if ((st
= mcdStatus()) != -1) {
813 if (st
& MST_DSK_CHG
) {
816 mcd_invalidate_buffers();
819 set_mode_immediately
:
821 if ((st
& MST_DOOR_OPEN
) || !(st
& MST_READY
)) {
824 if (mcd_transfer_is_active
) {
825 mcd_state
= MCD_S_START
;
828 printk((st
& MST_DOOR_OPEN
) ? "mcd: door open\n" : "mcd: disk removed\n");
829 mcd_state
= MCD_S_IDLE
;
830 while (CURRENT_VALID
)
835 outb(MCMD_SET_MODE
, MCDPORT(0));
838 mcd_state
= MCD_S_READ
;
848 printk("MCD_S_READ\n");
851 if ((st
= mcdStatus()) != -1) {
853 if (st
& MST_DSK_CHG
) {
856 mcd_invalidate_buffers();
861 if ((st
& MST_DOOR_OPEN
) || !(st
& MST_READY
)) {
864 if (mcd_transfer_is_active
) {
865 mcd_state
= MCD_S_START
;
868 printk((st
& MST_DOOR_OPEN
) ? "mcd: door open\n" : "mcd: disk removed\n");
869 mcd_state
= MCD_S_IDLE
;
870 while (CURRENT_VALID
)
876 struct mcd_Play_msf msf
;
877 mcd_next_bn
= CURRENT
-> sector
/ 4;
878 hsg2msf(mcd_next_bn
, &msf
.start
);
882 sendMcdCmd(MCMD_DATA_READ
, &msf
);
883 mcd_state
= MCD_S_DATA
;
884 McdTimeout
= READ_TIMEOUT
;
886 mcd_state
= MCD_S_STOP
;
896 printk("MCD_S_DATA\n");
899 st
= inb(MCDPORT(1)) & (MFL_STATUSorDATA
);
902 printk("Status %02x\n",st
);
907 #ifdef WARN_IF_READ_FAILURE
909 printk("mcd: read of block %d failed\n", mcd_next_bn
);
912 printk("mcd: read of block %d failed, giving up\n", mcd_next_bn
);
913 if (mcd_transfer_is_active
) {
921 mcd_state
= MCD_S_START
;
922 McdTimeout
= READ_TIMEOUT
;
925 case MFL_STATUSorDATA
:
930 if (!CURRENT_VALID
&& mcd_buf_in
== mcd_buf_out
) {
931 mcd_state
= MCD_S_STOP
;
934 mcd_buf_bn
[mcd_buf_in
] = -1;
935 READ_DATA(MCDPORT(0), mcd_buf
+ 2048 * mcd_buf_in
, 2048);
936 mcd_buf_bn
[mcd_buf_in
] = mcd_next_bn
++;
937 if (mcd_buf_out
== -1)
938 mcd_buf_out
= mcd_buf_in
;
939 mcd_buf_in
= mcd_buf_in
+ 1 == MCD_BUF_SIZ
? 0 : mcd_buf_in
+ 1;
940 if (!mcd_transfer_is_active
) {
941 while (CURRENT_VALID
) {
943 if (CURRENT
-> nr_sectors
== 0)
951 && (CURRENT
-> sector
/ 4 < mcd_next_bn
||
952 CURRENT
-> sector
/ 4 > mcd_next_bn
+ 16)) {
953 mcd_state
= MCD_S_STOP
;
956 McdTimeout
= READ_TIMEOUT
;
957 #ifdef DOUBLE_QUICK_ONLY
958 if (MCMD_DATA_READ
!= MCMD_PLAY_READ
)
961 int count
= QUICK_LOOP_COUNT
;
964 if ((st
= (inb(MCDPORT(1))) & (MFL_STATUSorDATA
)) != (MFL_STATUSorDATA
)) {
966 /* printk("Quickloop success at %d\n",QUICK_LOOP_COUNT-count); */
967 printk(" %d ",QUICK_LOOP_COUNT
-count
);
969 goto data_immediately
;
973 /* printk("Quickloop ended at %d\n",QUICK_LOOP_COUNT); */
985 printk("MCD_S_STOP\n");
988 #ifdef WORK_AROUND_MITSUMI_BUG_93
989 if (!mitsumi_bug_93_wait
)
990 goto do_not_work_around_mitsumi_bug_93_1
;
992 McdTimeout
= mitsumi_bug_93_wait
;
1000 do_not_work_around_mitsumi_bug_93_1
:
1001 #endif /* WORK_AROUND_MITSUMI_BUG_93 */
1003 outb(MCMD_STOP
, MCDPORT(0));
1005 #ifdef WORK_AROUND_MITSUMI_BUG_92
1006 if ((inb(MCDPORT(1)) & MFL_STATUSorDATA
) == MFL_STATUS
) {
1010 } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA
) == MFL_STATUS
&& --i
);
1011 outb(MCMD_STOP
, MCDPORT(0));
1012 if ((inb(MCDPORT(1)) & MFL_STATUSorDATA
) == MFL_STATUS
) {
1016 } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA
) == MFL_STATUS
&& --i
);
1017 outb(MCMD_STOP
, MCDPORT(0));
1020 #endif /* WORK_AROUND_MITSUMI_BUG_92 */
1022 mcd_state
= MCD_S_STOPPING
;
1026 case MCD_S_STOPPING
:
1028 printk("MCD_S_STOPPING\n");
1031 if ((st
= mcdStatus()) == -1 && McdTimeout
)
1034 if ((st
!= -1) && (st
& MST_DSK_CHG
)) {
1037 mcd_invalidate_buffers();
1040 #ifdef WORK_AROUND_MITSUMI_BUG_93
1041 if (!mitsumi_bug_93_wait
)
1042 goto do_not_work_around_mitsumi_bug_93_2
;
1044 McdTimeout
= mitsumi_bug_93_wait
;
1054 do_not_work_around_mitsumi_bug_93_2
:
1055 #endif /* WORK_AROUND_MITSUMI_BUG_93 */
1058 printk("CURRENT_VALID %d mcd_mode %d\n",
1059 CURRENT_VALID
, mcd_mode
);
1062 if (CURRENT_VALID
) {
1065 goto read_immediately
;
1067 goto set_mode_immediately
;
1069 mcd_state
= MCD_S_START
;
1073 mcd_state
= MCD_S_IDLE
;
1079 printk("mcd: invalid state %d\n", mcd_state
);
1084 if (!McdTimeout
--) {
1085 printk("mcd: timeout in state %d\n", mcd_state
);
1086 mcd_state
= MCD_S_STOP
;
1089 SET_TIMER(mcd_poll
, 1);
1095 mcd_invalidate_buffers(void)
1098 for (i
= 0; i
< MCD_BUF_SIZ
; ++i
)
1105 * Open the device special file. Check that a disk is in.
1107 static int mcd_open(struct cdrom_device_info
* cdi
, int purpose
)
1110 if (mcdPresent
== 0)
1111 return -ENXIO
; /* no hardware */
1113 if (!mcd_open_count
&& mcd_state
== MCD_S_IDLE
) {
1114 mcd_invalidate_buffers();
1116 st
= statusCmd(); /* check drive status */
1118 return -EIO
; /* drive doesn't respond */
1119 if ((st
& MST_READY
) == 0) { /* no disk? wait a sec... */
1120 current
->state
= TASK_INTERRUPTIBLE
;
1121 schedule_timeout(HZ
);
1123 } while (((st
& MST_READY
) == 0) && count
++ < MCD_RETRY_ATTEMPTS
);
1125 if (updateToc() < 0)
1135 * On close, we flush all mcd blocks from the buffer cache.
1137 static void mcd_release(struct cdrom_device_info
* cdi
)
1138 { MOD_DEC_USE_COUNT
;
1139 if (!--mcd_open_count
) {
1140 mcd_invalidate_buffers();
1146 /* This routine gets called during initialization if things go wrong,
1147 * and is used in mcd_exit as well. */
1148 static void cleanup(int level
)
1152 if (unregister_cdrom(&mcd_info
)) {
1153 printk(KERN_WARNING
"Can't unregister cdrom mcd\n");
1156 free_irq(mcd_irq
, NULL
);
1158 release_region(mcd_port
,4);
1160 if (devfs_unregister_blkdev(MAJOR_NR
, "mcd")) {
1161 printk(KERN_WARNING
"Can't unregister major mcd\n");
1171 * Test for presence of drive and initialize it. Called at boot time.
1174 int __init
mcd_init(void)
1177 unsigned char result
[3];
1180 if (mcd_port
<= 0 || mcd_irq
<= 0) {
1181 printk("skip mcd_init\n");
1185 if (devfs_register_blkdev(MAJOR_NR
, "mcd", &cdrom_fops
) != 0)
1187 printk("Unable to get major %d for Mitsumi CD-ROM\n",
1191 if (check_region(mcd_port
, 4)) {
1193 printk("Init failed, I/O port (%X) already in use\n",
1198 blksize_size
[MAJOR_NR
] = mcd_blocksizes
;
1199 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR
), DEVICE_REQUEST
);
1200 read_ahead
[MAJOR_NR
] = 4;
1202 /* check for card */
1204 outb(0, MCDPORT(1)); /* send reset */
1205 for (count
= 0; count
< 2000000; count
++)
1206 (void) inb(MCDPORT(1)); /* delay a bit */
1208 outb(0x40, MCDPORT(0)); /* send get-stat cmd */
1209 for (count
= 0; count
< 2000000; count
++)
1210 if (!(inb(MCDPORT(1)) & MFL_STATUS
))
1213 if (count
>= 2000000) {
1214 printk("Init failed. No mcd device at 0x%x irq %d\n",
1219 count
= inb(MCDPORT(0)); /* pick up the status */
1221 outb(MCMD_GET_VERSION
,MCDPORT(0));
1222 for(count
=0;count
<3;count
++)
1223 if(getValue(result
+count
)) {
1224 printk("mitsumi get version failed at 0x%d\n",
1230 if (result
[0] == result
[1] && result
[1] == result
[2]) {
1235 mcdVersion
=result
[2];
1238 outb(4,MCDPORT(2)); /* magic happens */
1240 /* don't get the IRQ until we know for sure the drive is there */
1242 if (request_irq(mcd_irq
, mcd_interrupt
, SA_INTERRUPT
, "Mitsumi CD", NULL
))
1244 printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq
);
1249 if (result
[1] == 'D')
1251 MCMD_DATA_READ
= MCMD_2X_READ
;
1252 /* Added flag to drop to 1x speed if too many errors */
1256 sprintf(msg
, " mcd: Mitsumi %s Speed CD-ROM at port=0x%x,"
1257 " irq=%d\n", mcd_info
.speed
== 1 ? "Single" : "Double", mcd_port
, mcd_irq
);
1259 request_region(mcd_port
, 4, "mcd");
1261 outb(MCMD_CONFIG_DRIVE
, MCDPORT(0));
1262 outb(0x02,MCDPORT(0));
1263 outb(0x00,MCDPORT(0));
1266 outb(MCMD_CONFIG_DRIVE
, MCDPORT(0));
1267 outb(0x10,MCDPORT(0));
1268 outb(0x04,MCDPORT(0));
1271 mcd_invalidate_buffers();
1274 mcd_info
.dev
= MKDEV(MAJOR_NR
,0);
1276 if (register_cdrom(&mcd_info
) != 0) {
1277 printk("Cannot register Mitsumi CD-ROM!\n");
1288 hsg2msf(long hsg
, struct msf
*msf
)
1291 msf
-> min
= hsg
/ 4500;
1293 msf
-> sec
= hsg
/ 75;
1294 msf
-> frame
= hsg
% 75;
1296 bin2bcd(&msf
-> min
); /* convert to BCD */
1297 bin2bcd(&msf
-> sec
);
1298 bin2bcd(&msf
-> frame
);
1303 bin2bcd(unsigned char *p
)
1313 bcd2bin(unsigned char bcd
)
1315 return (bcd
>> 4) * 10 + (bcd
& 0xF);
1320 * See if a status is ready from the drive and return it
1330 st
= inb(MCDPORT(1)) & MFL_STATUS
;
1333 i
= inb(MCDPORT(0)) & 0xFF;
1342 * Send a play or read command to the drive
1346 sendMcdCmd(int cmd
, struct mcd_Play_msf
*params
)
1348 outb(cmd
, MCDPORT(0));
1349 outb(params
-> start
.min
, MCDPORT(0));
1350 outb(params
-> start
.sec
, MCDPORT(0));
1351 outb(params
-> start
.frame
, MCDPORT(0));
1352 outb(params
-> end
.min
, MCDPORT(0));
1353 outb(params
-> end
.sec
, MCDPORT(0));
1354 outb(params
-> end
.frame
, MCDPORT(0));
1359 * Timer interrupt routine to test for status ready from the drive.
1360 * (see the next routine)
1366 if (!(inb(MCDPORT(1)) & MFL_STATUS
))
1368 wake_up(&mcd_waitq
);
1373 if (McdTimeout
<= 0)
1375 wake_up(&mcd_waitq
);
1379 SET_TIMER(mcdStatTimer
, 1);
1384 * Wait for a status to be returned from the drive. The actual test
1385 * (see routine above) is done by the timer interrupt to avoid
1386 * excessive rescheduling.
1390 getMcdStatus(int timeout
)
1394 McdTimeout
= timeout
;
1395 SET_TIMER(mcdStatTimer
, 1);
1396 sleep_on(&mcd_waitq
);
1397 if (McdTimeout
<= 0)
1400 st
= inb(MCDPORT(0)) & 0xFF;
1404 if ((st
& MST_BUSY
) == 0 && audioStatus
== CDROM_AUDIO_PLAY
)
1405 /* XXX might be an error? look at q-channel? */
1406 audioStatus
= CDROM_AUDIO_COMPLETED
;
1408 if (st
& MST_DSK_CHG
)
1412 audioStatus
= CDROM_AUDIO_NO_STATUS
;
1419 /* gives current state of the drive This function is quite unreliable,
1420 and should probably be rewritten by someone, eventually... */
1421 int mcd_drive_status(struct cdrom_device_info
* cdi
, int slot_nr
)
1425 st
= statusCmd(); /* check drive status */
1427 return -EIO
; /* drive doesn't respond */
1428 if ((st
& MST_READY
)) return CDS_DISC_OK
;
1429 if ((st
& MST_DOOR_OPEN
)) return CDS_TRAY_OPEN
;
1430 if ((st
& MST_DSK_CHG
)) return CDS_NO_DISC
;
1431 if ((st
& MST_BUSY
)) return CDS_DRIVE_NOT_READY
;
1437 * Read a value from the drive.
1441 getValue(unsigned char *result
)
1446 for (count
= 0; count
< 2000; count
++)
1447 if (!(inb(MCDPORT(1)) & MFL_STATUS
))
1452 printk("mcd: getValue timeout\n");
1456 s
= inb(MCDPORT(0)) & 0xFF;
1457 *result
= (unsigned char) s
;
1463 * Read the current Q-channel info. Also used for reading the
1464 * table of contents.
1468 GetQChannelInfo(struct mcd_Toc
*qp
)
1470 unsigned char notUsed
;
1473 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
1475 outb(MCMD_GET_Q_CHANNEL
, MCDPORT(0));
1476 if (getMcdStatus(MCD_STATUS_DELAY
) != -1)
1480 if (retry
>= MCD_RETRY_ATTEMPTS
)
1483 if (getValue(&qp
-> ctrl_addr
) < 0) return -1;
1484 if (getValue(&qp
-> track
) < 0) return -1;
1485 if (getValue(&qp
-> pointIndex
) < 0) return -1;
1486 if (getValue(&qp
-> trackTime
.min
) < 0) return -1;
1487 if (getValue(&qp
-> trackTime
.sec
) < 0) return -1;
1488 if (getValue(&qp
-> trackTime
.frame
) < 0) return -1;
1489 if (getValue(¬Used
) < 0) return -1;
1490 if (getValue(&qp
-> diskTime
.min
) < 0) return -1;
1491 if (getValue(&qp
-> diskTime
.sec
) < 0) return -1;
1492 if (getValue(&qp
-> diskTime
.frame
) < 0) return -1;
1499 * Read the table of contents (TOC) and TOC header if necessary
1508 if (GetDiskInfo() < 0)
1520 * Read the table of contents header
1528 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
1530 outb(MCMD_GET_DISK_INFO
, MCDPORT(0));
1531 if (getMcdStatus(MCD_STATUS_DELAY
) != -1)
1535 if (retry
>= MCD_RETRY_ATTEMPTS
)
1538 if (getValue(&DiskInfo
.first
) < 0) return -1;
1539 if (getValue(&DiskInfo
.last
) < 0) return -1;
1541 DiskInfo
.first
= bcd2bin(DiskInfo
.first
);
1542 DiskInfo
.last
= bcd2bin(DiskInfo
.last
);
1545 printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
1548 DiskInfo
.diskLength
.min
,
1549 DiskInfo
.diskLength
.sec
,
1550 DiskInfo
.diskLength
.frame
,
1551 DiskInfo
.firstTrack
.min
,
1552 DiskInfo
.firstTrack
.sec
,
1553 DiskInfo
.firstTrack
.frame
);
1556 if (getValue(&DiskInfo
.diskLength
.min
) < 0) return -1;
1557 if (getValue(&DiskInfo
.diskLength
.sec
) < 0) return -1;
1558 if (getValue(&DiskInfo
.diskLength
.frame
) < 0) return -1;
1559 if (getValue(&DiskInfo
.firstTrack
.min
) < 0) return -1;
1560 if (getValue(&DiskInfo
.firstTrack
.sec
) < 0) return -1;
1561 if (getValue(&DiskInfo
.firstTrack
.frame
) < 0) return -1;
1568 * Read the table of contents (TOC)
1577 struct mcd_Toc qInfo
;
1579 for (i
= 0; i
< MAX_TRACKS
; i
++)
1580 Toc
[i
].pointIndex
= 0;
1582 i
= DiskInfo
.last
+ 3;
1584 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
1586 outb(MCMD_STOP
, MCDPORT(0));
1587 if (getMcdStatus(MCD_STATUS_DELAY
) != -1)
1591 if (retry
>= MCD_RETRY_ATTEMPTS
)
1594 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
1596 outb(MCMD_SET_MODE
, MCDPORT(0));
1597 outb(0x05, MCDPORT(0)); /* mode: toc */
1599 if (getMcdStatus(MCD_STATUS_DELAY
) != -1)
1603 if (retry
>= MCD_RETRY_ATTEMPTS
)
1606 for (limit
= 300; limit
> 0; limit
--)
1608 if (GetQChannelInfo(&qInfo
) < 0)
1611 px
= bcd2bin(qInfo
.pointIndex
);
1612 if (px
> 0 && px
< MAX_TRACKS
&& qInfo
.track
== 0)
1613 if (Toc
[px
].pointIndex
== 0)
1623 Toc
[DiskInfo
.last
+ 1].diskTime
= DiskInfo
.diskLength
;
1625 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
1627 outb(MCMD_SET_MODE
, MCDPORT(0));
1628 outb(0x01, MCDPORT(0));
1630 if (getMcdStatus(MCD_STATUS_DELAY
) != -1)
1635 for (i
= 1; i
<= DiskInfo
.last
; i
++)
1636 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1637 i
, Toc
[i
].ctrl_addr
, Toc
[i
].track
, Toc
[i
].pointIndex
,
1638 Toc
[i
].trackTime
.min
, Toc
[i
].trackTime
.sec
, Toc
[i
].trackTime
.frame
,
1639 Toc
[i
].diskTime
.min
, Toc
[i
].diskTime
.sec
, Toc
[i
].diskTime
.frame
);
1640 for (i
= 100; i
< 103; i
++)
1641 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1642 i
, Toc
[i
].ctrl_addr
, Toc
[i
].track
, Toc
[i
].pointIndex
,
1643 Toc
[i
].trackTime
.min
, Toc
[i
].trackTime
.sec
, Toc
[i
].trackTime
.frame
,
1644 Toc
[i
].diskTime
.min
, Toc
[i
].diskTime
.sec
, Toc
[i
].diskTime
.frame
);
1647 return limit
> 0 ? 0 : -1;
1651 void __exit
mcd_exit(void)
1657 module_init(mcd_init
);
1659 module_exit(mcd_exit
);