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(unsigned long dummy
);
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 timer_list mcd_timer
;
208 static struct cdrom_device_ops mcd_dops
= {
210 mcd_release
, /* release */
211 mcd_drive_status
, /* drive status */
212 //NULL, /* drive status */
213 mcd_media_changed
, /* media changed */
214 mcd_tray_move
, /* tray move */
215 NULL
, /* lock door */
216 NULL
, /* select speed */
217 NULL
, /* select disc */
218 NULL
, /* get last session */
219 NULL
, /* get universal product code */
220 NULL
, /* hard reset */
221 mcd_audio_ioctl
, /* audio ioctl */
222 NULL
, /* device-specific ioctl */
223 CDC_OPEN_TRAY
| CDC_MEDIA_CHANGED
| CDC_PLAY_AUDIO
224 | CDC_DRIVE_STATUS
, /* capability */
225 0, /* number of minor devices */
228 static struct cdrom_device_info mcd_info
= {
229 &mcd_dops
, /* device operations */
234 2, /* maximum speed */
235 1, /* number of discs */
236 0, /* options, not owned */
237 0, /* mc_flags, not owned */
238 0, /* use count, not owned */
239 "mcd", /* name of the device type */
243 static int __init
mcd_setup(char *str
)
247 (void)get_options(str
, ARRAY_SIZE(ints
), ints
);
253 #ifdef WORK_AROUND_MITSUMI_BUG_93
255 mitsumi_bug_93_wait
= ints
[3];
256 #endif /* WORK_AROUND_MITSUMI_BUG_93 */
261 __setup("mcd=", mcd_setup
);
265 static int mcd_media_changed(struct cdrom_device_info
* cdi
, int disc_nr
)
270 #if 1 /* the below is not reliable */
275 printk("mcd: Mitsumi CD-ROM request error: invalid device.\n");
279 retval
= mcdDiskChanged
;
287 * Do a 'get status' command and get the result. Only use from the top half
288 * because it calls 'getMcdStatus' which sleeps.
296 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
298 outb(MCMD_GET_STATUS
, MCDPORT(0)); /* send get-status cmd */
300 st
= getMcdStatus(MCD_STATUS_DELAY
);
310 * Send a 'Play' command and get the status. Use only from the top half.
314 mcdPlay(struct mcd_Play_msf
*arg
)
318 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
320 sendMcdCmd(MCMD_PLAY_READ
, arg
);
321 st
= getMcdStatus(2 * MCD_STATUS_DELAY
);
331 mcd_tray_move(struct cdrom_device_info
* cdi
, int position
)
336 /* all drives can at least stop! */
337 if (audioStatus
== CDROM_AUDIO_PLAY
) {
338 outb(MCMD_STOP
, MCDPORT(0));
339 i
= getMcdStatus(MCD_STATUS_DELAY
);
342 audioStatus
= CDROM_AUDIO_NO_STATUS
;
344 outb(MCMD_EJECT
, MCDPORT(0));
346 * the status (i) shows failure on all but the FX drives.
347 * But nothing we can do about that in software!
348 * So just read the status and forget it. - Jon.
350 i
= getMcdStatus(MCD_STATUS_DELAY
);
358 msf2hsg(struct msf
*mp
)
360 return bcd2bin(mp
-> frame
)
361 + bcd2bin(mp
-> sec
) * 75
362 + bcd2bin(mp
-> min
) * 4500
367 int mcd_audio_ioctl(struct cdrom_device_info
* cdi
, unsigned int cmd
,
371 struct mcd_Toc qInfo
;
373 struct cdrom_tochdr
*tocHdr
;
374 struct cdrom_msf
*msf
;
375 struct cdrom_subchnl
*subchnl
;
376 struct cdrom_tocentry
*entry
;
377 struct mcd_Toc
*tocPtr
;
378 struct cdrom_volctrl
*volctrl
;
388 return i
; /* error reading TOC */
393 case CDROMSTART
: /* Spin up the drive */
394 /* Don't think we can do this. Even if we could,
395 * I think the drive times out and stops after a while
396 * anyway. For now, ignore it.
401 case CDROMSTOP
: /* Spin down the drive */
402 outb(MCMD_STOP
, MCDPORT(0));
403 i
= getMcdStatus(MCD_STATUS_DELAY
);
405 /* should we do anything if it fails? */
407 audioStatus
= CDROM_AUDIO_NO_STATUS
;
410 case CDROMPAUSE
: /* Pause the drive */
411 if (audioStatus
!= CDROM_AUDIO_PLAY
)
414 outb(MCMD_STOP
, MCDPORT(0));
415 i
= getMcdStatus(MCD_STATUS_DELAY
);
417 if (GetQChannelInfo(&qInfo
) < 0)
419 /* didn't get q channel info */
421 audioStatus
= CDROM_AUDIO_NO_STATUS
;
425 mcd_Play
.start
= qInfo
.diskTime
; /* remember restart point */
427 audioStatus
= CDROM_AUDIO_PAUSED
;
430 case CDROMRESUME
: /* Play it again, Sam */
431 if (audioStatus
!= CDROM_AUDIO_PAUSED
)
434 /* restart the drive at the saved position. */
436 i
= mcdPlay(&mcd_Play
);
439 audioStatus
= CDROM_AUDIO_ERROR
;
443 audioStatus
= CDROM_AUDIO_PLAY
;
446 case CDROMPLAYTRKIND
: /* Play a track. This currently ignores index. */
448 ti
=(struct cdrom_ti
*) arg
;
450 if (ti
->cdti_trk0
< DiskInfo
.first
451 || ti
->cdti_trk0
> DiskInfo
.last
452 || ti
->cdti_trk1
< ti
->cdti_trk0
)
457 if (ti
->cdti_trk1
> DiskInfo
.last
)
458 ti
->cdti_trk1
= DiskInfo
.last
;
460 mcd_Play
.start
= Toc
[ti
->cdti_trk0
].diskTime
;
461 mcd_Play
.end
= Toc
[ti
->cdti_trk1
+ 1].diskTime
;
464 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
465 mcd_Play
.start
.min
, mcd_Play
.start
.sec
, mcd_Play
.start
.frame
,
466 mcd_Play
.end
.min
, mcd_Play
.end
.sec
, mcd_Play
.end
.frame
);
469 i
= mcdPlay(&mcd_Play
);
472 audioStatus
= CDROM_AUDIO_ERROR
;
476 audioStatus
= CDROM_AUDIO_PLAY
;
479 case CDROMPLAYMSF
: /* Play starting at the given MSF address. */
481 if (audioStatus
== CDROM_AUDIO_PLAY
) {
482 outb(MCMD_STOP
, MCDPORT(0));
483 i
= getMcdStatus(MCD_STATUS_DELAY
);
484 audioStatus
= CDROM_AUDIO_NO_STATUS
;
487 msf
=(struct cdrom_msf
*) arg
;
491 bin2bcd(&msf
->cdmsf_min0
);
492 bin2bcd(&msf
->cdmsf_sec0
);
493 bin2bcd(&msf
->cdmsf_frame0
);
494 bin2bcd(&msf
->cdmsf_min1
);
495 bin2bcd(&msf
->cdmsf_sec1
);
496 bin2bcd(&msf
->cdmsf_frame1
);
498 mcd_Play
.start
.min
= msf
->cdmsf_min0
;
499 mcd_Play
.start
.sec
= msf
->cdmsf_sec0
;
500 mcd_Play
.start
.frame
= msf
->cdmsf_frame0
;
501 mcd_Play
.end
.min
= msf
->cdmsf_min1
;
502 mcd_Play
.end
.sec
= msf
->cdmsf_sec1
;
503 mcd_Play
.end
.frame
= msf
->cdmsf_frame1
;
506 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
507 mcd_Play
.start
.min
, mcd_Play
.start
.sec
, mcd_Play
.start
.frame
,
508 mcd_Play
.end
.min
, mcd_Play
.end
.sec
, mcd_Play
.end
.frame
);
511 i
= mcdPlay(&mcd_Play
);
514 audioStatus
= CDROM_AUDIO_ERROR
;
518 audioStatus
= CDROM_AUDIO_PLAY
;
521 case CDROMREADTOCHDR
: /* Read the table of contents header */
522 tocHdr
=(struct cdrom_tochdr
*) arg
;
523 tocHdr
->cdth_trk0
= DiskInfo
.first
;
524 tocHdr
->cdth_trk1
= DiskInfo
.last
;
527 case CDROMREADTOCENTRY
: /* Read an entry in the table of contents */
528 entry
=(struct cdrom_tocentry
*) arg
;
529 if (entry
->cdte_track
== CDROM_LEADOUT
)
530 tocPtr
= &Toc
[DiskInfo
.last
- DiskInfo
.first
+ 1];
532 else if (entry
->cdte_track
> DiskInfo
.last
533 || entry
->cdte_track
< DiskInfo
.first
)
537 tocPtr
= &Toc
[entry
->cdte_track
];
539 entry
->cdte_adr
= tocPtr
-> ctrl_addr
;
540 entry
->cdte_ctrl
= tocPtr
-> ctrl_addr
>> 4;
542 if (entry
->cdte_format
== CDROM_LBA
)
543 entry
->cdte_addr
.lba
= msf2hsg(&tocPtr
-> diskTime
);
545 else if (entry
->cdte_format
== CDROM_MSF
)
547 entry
->cdte_addr
.msf
.minute
= bcd2bin(tocPtr
-> diskTime
.min
);
548 entry
->cdte_addr
.msf
.second
= bcd2bin(tocPtr
-> diskTime
.sec
);
549 entry
->cdte_addr
.msf
.frame
= bcd2bin(tocPtr
-> diskTime
.frame
);
557 case CDROMSUBCHNL
: /* Get subchannel info */
559 subchnl
=(struct cdrom_subchnl
*) arg
;
560 if (GetQChannelInfo(&qInfo
) < 0)
563 subchnl
->cdsc_audiostatus
= audioStatus
;
564 subchnl
->cdsc_adr
= qInfo
.ctrl_addr
;
565 subchnl
->cdsc_ctrl
= qInfo
.ctrl_addr
>> 4;
566 subchnl
->cdsc_trk
= bcd2bin(qInfo
.track
);
567 subchnl
->cdsc_ind
= bcd2bin(qInfo
.pointIndex
);
568 subchnl
->cdsc_absaddr
.msf
.minute
= bcd2bin(qInfo
.diskTime
.min
);
569 subchnl
->cdsc_absaddr
.msf
.second
= bcd2bin(qInfo
.diskTime
.sec
);
570 subchnl
->cdsc_absaddr
.msf
.frame
= bcd2bin(qInfo
.diskTime
.frame
);
571 subchnl
->cdsc_reladdr
.msf
.minute
= bcd2bin(qInfo
.trackTime
.min
);
572 subchnl
->cdsc_reladdr
.msf
.second
= bcd2bin(qInfo
.trackTime
.sec
);
573 subchnl
->cdsc_reladdr
.msf
.frame
= bcd2bin(qInfo
.trackTime
.frame
);
576 case CDROMVOLCTRL
: /* Volume control */
577 volctrl
=(struct cdrom_volctrl
*) arg
;
578 outb(MCMD_SET_VOLUME
, MCDPORT(0));
579 outb(volctrl
->channel0
, MCDPORT(0));
580 outb(255, MCDPORT(0));
581 outb(volctrl
->channel1
, MCDPORT(0));
582 outb(255, MCDPORT(0));
584 i
= getMcdStatus(MCD_STATUS_DELAY
);
605 * Take care of the different block sizes between cdrom and Linux.
606 * When Linux gets variable block sizes this will probably go away.
613 while (CURRENT
-> nr_sectors
) {
614 int bn
= CURRENT
-> sector
/ 4;
616 for (i
= 0; i
< MCD_BUF_SIZ
&& mcd_buf_bn
[i
] != bn
; ++i
)
618 if (i
< MCD_BUF_SIZ
) {
619 int offs
= (i
* 4 + (CURRENT
-> sector
& 3)) * 512;
620 int nr_sectors
= 4 - (CURRENT
-> sector
& 3);
621 if (mcd_buf_out
!= i
) {
623 if (mcd_buf_bn
[i
] != bn
) {
628 if (nr_sectors
> CURRENT
-> nr_sectors
)
629 nr_sectors
= CURRENT
-> nr_sectors
;
630 memcpy(CURRENT
-> buffer
, mcd_buf
+ offs
, nr_sectors
* 512);
631 CURRENT
-> nr_sectors
-= nr_sectors
;
632 CURRENT
-> sector
+= nr_sectors
;
633 CURRENT
-> buffer
+= nr_sectors
* 512;
644 * We only seem to get interrupts after an error.
645 * Just take the interrupt and clear out the status reg.
649 mcd_interrupt(int irq
, void *dev_id
, struct pt_regs
* regs
)
653 st
= inb(MCDPORT(1)) & 0xFF;
655 printk("<int1-%02X>", st
);
657 if (!(st
& MFL_STATUS
))
659 st
= inb(MCDPORT(0)) & 0xFF;
661 printk("<int0-%02X>", st
);
663 if ((st
& 0xFF) != 0xFF)
664 mcd_error
= st
? st
& 0xFF : -1;
670 do_mcd_request(request_queue_t
* q
)
673 printk(" do_mcd_request(%ld+%ld)\n", CURRENT
-> sector
, CURRENT
-> nr_sectors
);
675 mcd_transfer_is_active
= 1;
676 while (CURRENT_VALID
) {
678 if (!buffer_locked(CURRENT
->bh
))
679 panic(DEVICE_NAME
": block not locked");
682 if (CURRENT
-> nr_sectors
== 0) {
685 mcd_buf_out
= -1; /* Want to read a block not in buffer */
686 if (mcd_state
== MCD_S_IDLE
) {
688 if (updateToc() < 0) {
689 while (CURRENT_VALID
)
694 mcd_state
= MCD_S_START
;
696 SET_TIMER(mcd_poll
, 1);
701 mcd_transfer_is_active
= 0;
703 printk(" do_mcd_request ends\n");
710 mcd_poll(unsigned long dummy
)
717 if (mcd_error
& 0xA5)
719 printk("mcd: I/O error 0x%02x", mcd_error
);
720 if (mcd_error
& 0x80)
721 printk(" (Door open)");
722 if (mcd_error
& 0x20)
723 printk(" (Disk changed)");
724 if (mcd_error
& 0x04)
726 printk(" (Read error)"); /* Bitch about the problem. */
728 /* Time to get fancy! If at 2x speed and 1 error, drop to 1x speed! */
729 /* Interesting how it STAYS at MCD_RETRY_ATTEMPTS on first error! */
730 /* But I find that rather HANDY!!! */
731 /* Neat! it REALLY WORKS on those LOW QUALITY CD's!!! Smile! :) */
734 /* Slap the CD down to single speed! */
735 if (mcdDouble
== 1 && McdTries
== MCD_RETRY_ATTEMPTS
&& MCMD_DATA_READ
== MCMD_2X_READ
)
737 MCMD_DATA_READ
= MCMD_PLAY_READ
; /* Uhhh, Ummmm, muhuh-huh! */
738 mcd1xhold
= SINGLE_HOLD_SECTORS
; /* Hey Beavis! */
739 printk(" Speed now 1x"); /* Pull my finger! */
743 mcd_invalidate_buffers();
744 #ifdef WARN_IF_READ_FAILURE
745 if (McdTries
== MCD_RETRY_ATTEMPTS
)
746 printk("mcd: read of block %d failed\n", mcd_next_bn
);
750 /* Nuts! This cd is ready for recycling! */
751 /* When WAS the last time YOU cleaned it CORRECTLY?! */
752 printk("mcd: read of block %d failed, giving up\n", mcd_next_bn
);
753 if (mcd_transfer_is_active
)
760 McdTries
= MCD_RETRY_ATTEMPTS
;
764 mcd_state
= MCD_S_STOP
;
766 /* Switch back to Double speed if enough GOOD sectors were read! */
768 /* Are we a double speed with a crappy CD?! */
769 if (mcdDouble
== 1 && McdTries
== MCD_RETRY_ATTEMPTS
&& MCMD_DATA_READ
== MCMD_PLAY_READ
)
771 /* We ARE a double speed and we ARE bitching! */
772 if (mcd1xhold
== 0) /* Okay, Like are we STILL at single speed? */
773 { /* We need to switch back to double speed now... */
774 MCMD_DATA_READ
= MCMD_2X_READ
; /* Uhhh... BACK You GO! */
775 printk("mcd: Switching back to 2X speed!\n"); /* Tell 'em! */
777 else mcd1xhold
--; /* No?! Count down the good reads some more... */
778 /* and try, try again! */
790 printk("MCD_S_IDLE\n");
798 printk("MCD_S_START\n");
801 outb(MCMD_GET_STATUS
, MCDPORT(0));
802 mcd_state
= mcd_mode
== 1 ? MCD_S_READ
: MCD_S_MODE
;
810 printk("MCD_S_MODE\n");
813 if ((st
= mcdStatus()) != -1) {
815 if (st
& MST_DSK_CHG
) {
818 mcd_invalidate_buffers();
821 set_mode_immediately
:
823 if ((st
& MST_DOOR_OPEN
) || !(st
& MST_READY
)) {
826 if (mcd_transfer_is_active
) {
827 mcd_state
= MCD_S_START
;
830 printk((st
& MST_DOOR_OPEN
) ? "mcd: door open\n" : "mcd: disk removed\n");
831 mcd_state
= MCD_S_IDLE
;
832 while (CURRENT_VALID
)
837 outb(MCMD_SET_MODE
, MCDPORT(0));
840 mcd_state
= MCD_S_READ
;
850 printk("MCD_S_READ\n");
853 if ((st
= mcdStatus()) != -1) {
855 if (st
& MST_DSK_CHG
) {
858 mcd_invalidate_buffers();
863 if ((st
& MST_DOOR_OPEN
) || !(st
& MST_READY
)) {
866 if (mcd_transfer_is_active
) {
867 mcd_state
= MCD_S_START
;
870 printk((st
& MST_DOOR_OPEN
) ? "mcd: door open\n" : "mcd: disk removed\n");
871 mcd_state
= MCD_S_IDLE
;
872 while (CURRENT_VALID
)
878 struct mcd_Play_msf msf
;
879 mcd_next_bn
= CURRENT
-> sector
/ 4;
880 hsg2msf(mcd_next_bn
, &msf
.start
);
884 sendMcdCmd(MCMD_DATA_READ
, &msf
);
885 mcd_state
= MCD_S_DATA
;
886 McdTimeout
= READ_TIMEOUT
;
888 mcd_state
= MCD_S_STOP
;
898 printk("MCD_S_DATA\n");
901 st
= inb(MCDPORT(1)) & (MFL_STATUSorDATA
);
904 printk("Status %02x\n",st
);
909 #ifdef WARN_IF_READ_FAILURE
911 printk("mcd: read of block %d failed\n", mcd_next_bn
);
914 printk("mcd: read of block %d failed, giving up\n", mcd_next_bn
);
915 if (mcd_transfer_is_active
) {
923 mcd_state
= MCD_S_START
;
924 McdTimeout
= READ_TIMEOUT
;
927 case MFL_STATUSorDATA
:
932 if (!CURRENT_VALID
&& mcd_buf_in
== mcd_buf_out
) {
933 mcd_state
= MCD_S_STOP
;
936 mcd_buf_bn
[mcd_buf_in
] = -1;
937 READ_DATA(MCDPORT(0), mcd_buf
+ 2048 * mcd_buf_in
, 2048);
938 mcd_buf_bn
[mcd_buf_in
] = mcd_next_bn
++;
939 if (mcd_buf_out
== -1)
940 mcd_buf_out
= mcd_buf_in
;
941 mcd_buf_in
= mcd_buf_in
+ 1 == MCD_BUF_SIZ
? 0 : mcd_buf_in
+ 1;
942 if (!mcd_transfer_is_active
) {
943 while (CURRENT_VALID
) {
945 if (CURRENT
-> nr_sectors
== 0)
953 && (CURRENT
-> sector
/ 4 < mcd_next_bn
||
954 CURRENT
-> sector
/ 4 > mcd_next_bn
+ 16)) {
955 mcd_state
= MCD_S_STOP
;
958 McdTimeout
= READ_TIMEOUT
;
959 #ifdef DOUBLE_QUICK_ONLY
960 if (MCMD_DATA_READ
!= MCMD_PLAY_READ
)
963 int count
= QUICK_LOOP_COUNT
;
966 if ((st
= (inb(MCDPORT(1))) & (MFL_STATUSorDATA
)) != (MFL_STATUSorDATA
)) {
968 /* printk("Quickloop success at %d\n",QUICK_LOOP_COUNT-count); */
969 printk(" %d ",QUICK_LOOP_COUNT
-count
);
971 goto data_immediately
;
975 /* printk("Quickloop ended at %d\n",QUICK_LOOP_COUNT); */
987 printk("MCD_S_STOP\n");
990 #ifdef WORK_AROUND_MITSUMI_BUG_93
991 if (!mitsumi_bug_93_wait
)
992 goto do_not_work_around_mitsumi_bug_93_1
;
994 McdTimeout
= mitsumi_bug_93_wait
;
1002 do_not_work_around_mitsumi_bug_93_1
:
1003 #endif /* WORK_AROUND_MITSUMI_BUG_93 */
1005 outb(MCMD_STOP
, MCDPORT(0));
1007 #ifdef WORK_AROUND_MITSUMI_BUG_92
1008 if ((inb(MCDPORT(1)) & MFL_STATUSorDATA
) == MFL_STATUS
) {
1012 } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA
) == MFL_STATUS
&& --i
);
1013 outb(MCMD_STOP
, MCDPORT(0));
1014 if ((inb(MCDPORT(1)) & MFL_STATUSorDATA
) == MFL_STATUS
) {
1018 } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA
) == MFL_STATUS
&& --i
);
1019 outb(MCMD_STOP
, MCDPORT(0));
1022 #endif /* WORK_AROUND_MITSUMI_BUG_92 */
1024 mcd_state
= MCD_S_STOPPING
;
1028 case MCD_S_STOPPING
:
1030 printk("MCD_S_STOPPING\n");
1033 if ((st
= mcdStatus()) == -1 && McdTimeout
)
1036 if ((st
!= -1) && (st
& MST_DSK_CHG
)) {
1039 mcd_invalidate_buffers();
1042 #ifdef WORK_AROUND_MITSUMI_BUG_93
1043 if (!mitsumi_bug_93_wait
)
1044 goto do_not_work_around_mitsumi_bug_93_2
;
1046 McdTimeout
= mitsumi_bug_93_wait
;
1056 do_not_work_around_mitsumi_bug_93_2
:
1057 #endif /* WORK_AROUND_MITSUMI_BUG_93 */
1060 printk("CURRENT_VALID %d mcd_mode %d\n",
1061 CURRENT_VALID
, mcd_mode
);
1064 if (CURRENT_VALID
) {
1067 goto read_immediately
;
1069 goto set_mode_immediately
;
1071 mcd_state
= MCD_S_START
;
1075 mcd_state
= MCD_S_IDLE
;
1081 printk("mcd: invalid state %d\n", mcd_state
);
1086 if (!McdTimeout
--) {
1087 printk("mcd: timeout in state %d\n", mcd_state
);
1088 mcd_state
= MCD_S_STOP
;
1091 SET_TIMER(mcd_poll
, 1);
1099 mcd_invalidate_buffers(void)
1102 for (i
= 0; i
< MCD_BUF_SIZ
; ++i
)
1109 * Open the device special file. Check that a disk is in.
1111 static int mcd_open(struct cdrom_device_info
* cdi
, int purpose
)
1114 if (mcdPresent
== 0)
1115 return -ENXIO
; /* no hardware */
1119 if (mcd_open_count
|| mcd_state
!= MCD_S_IDLE
)
1122 mcd_invalidate_buffers();
1124 st
= statusCmd(); /* check drive status */
1126 goto err_out
; /* drive doesn't respond */
1127 if ((st
& MST_READY
) == 0) { /* no disk? wait a sec... */
1128 current
->state
= TASK_INTERRUPTIBLE
;
1129 schedule_timeout(HZ
);
1131 } while (((st
& MST_READY
) == 0) && count
++ < MCD_RETRY_ATTEMPTS
);
1133 if (updateToc() < 0)
1147 * On close, we flush all mcd blocks from the buffer cache.
1149 static void mcd_release(struct cdrom_device_info
* cdi
)
1150 { MOD_DEC_USE_COUNT
;
1151 if (!--mcd_open_count
) {
1152 mcd_invalidate_buffers();
1158 /* This routine gets called during initialization if things go wrong,
1159 * and is used in mcd_exit as well. */
1160 static void cleanup(int level
)
1164 if (unregister_cdrom(&mcd_info
)) {
1165 printk(KERN_WARNING
"Can't unregister cdrom mcd\n");
1168 free_irq(mcd_irq
, NULL
);
1170 release_region(mcd_port
,4);
1172 if (devfs_unregister_blkdev(MAJOR_NR
, "mcd")) {
1173 printk(KERN_WARNING
"Can't unregister major mcd\n");
1176 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR
));
1184 * Test for presence of drive and initialize it. Called at boot time.
1187 int __init
mcd_init(void)
1190 unsigned char result
[3];
1193 if (mcd_port
<= 0 || mcd_irq
<= 0) {
1194 printk("skip mcd_init\n");
1198 if (devfs_register_blkdev(MAJOR_NR
, "mcd", &cdrom_fops
) != 0)
1200 printk("Unable to get major %d for Mitsumi CD-ROM\n",
1204 if (check_region(mcd_port
, 4)) {
1206 printk("Init failed, I/O port (%X) already in use\n",
1211 blksize_size
[MAJOR_NR
] = mcd_blocksizes
;
1212 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR
), DEVICE_REQUEST
);
1213 read_ahead
[MAJOR_NR
] = 4;
1215 /* check for card */
1217 outb(0, MCDPORT(1)); /* send reset */
1218 for (count
= 0; count
< 2000000; count
++)
1219 (void) inb(MCDPORT(1)); /* delay a bit */
1221 outb(0x40, MCDPORT(0)); /* send get-stat cmd */
1222 for (count
= 0; count
< 2000000; count
++)
1223 if (!(inb(MCDPORT(1)) & MFL_STATUS
))
1226 if (count
>= 2000000) {
1227 printk("Init failed. No mcd device at 0x%x irq %d\n",
1232 count
= inb(MCDPORT(0)); /* pick up the status */
1234 outb(MCMD_GET_VERSION
,MCDPORT(0));
1235 for(count
=0;count
<3;count
++)
1236 if(getValue(result
+count
)) {
1237 printk("mitsumi get version failed at 0x%d\n",
1243 if (result
[0] == result
[1] && result
[1] == result
[2]) {
1248 mcdVersion
=result
[2];
1251 outb(4,MCDPORT(2)); /* magic happens */
1253 /* don't get the IRQ until we know for sure the drive is there */
1255 if (request_irq(mcd_irq
, mcd_interrupt
, SA_INTERRUPT
, "Mitsumi CD", NULL
))
1257 printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq
);
1262 if (result
[1] == 'D')
1264 MCMD_DATA_READ
= MCMD_2X_READ
;
1265 /* Added flag to drop to 1x speed if too many errors */
1269 sprintf(msg
, " mcd: Mitsumi %s Speed CD-ROM at port=0x%x,"
1270 " irq=%d\n", mcd_info
.speed
== 1 ? "Single" : "Double", mcd_port
, mcd_irq
);
1272 request_region(mcd_port
, 4, "mcd");
1274 outb(MCMD_CONFIG_DRIVE
, MCDPORT(0));
1275 outb(0x02,MCDPORT(0));
1276 outb(0x00,MCDPORT(0));
1279 outb(MCMD_CONFIG_DRIVE
, MCDPORT(0));
1280 outb(0x10,MCDPORT(0));
1281 outb(0x04,MCDPORT(0));
1284 mcd_invalidate_buffers();
1287 mcd_info
.dev
= MKDEV(MAJOR_NR
,0);
1289 if (register_cdrom(&mcd_info
) != 0) {
1290 printk("Cannot register Mitsumi CD-ROM!\n");
1301 hsg2msf(long hsg
, struct msf
*msf
)
1304 msf
-> min
= hsg
/ 4500;
1306 msf
-> sec
= hsg
/ 75;
1307 msf
-> frame
= hsg
% 75;
1309 bin2bcd(&msf
-> min
); /* convert to BCD */
1310 bin2bcd(&msf
-> sec
);
1311 bin2bcd(&msf
-> frame
);
1316 bin2bcd(unsigned char *p
)
1326 bcd2bin(unsigned char bcd
)
1328 return (bcd
>> 4) * 10 + (bcd
& 0xF);
1333 * See if a status is ready from the drive and return it
1343 st
= inb(MCDPORT(1)) & MFL_STATUS
;
1346 i
= inb(MCDPORT(0)) & 0xFF;
1355 * Send a play or read command to the drive
1359 sendMcdCmd(int cmd
, struct mcd_Play_msf
*params
)
1361 outb(cmd
, MCDPORT(0));
1362 outb(params
-> start
.min
, MCDPORT(0));
1363 outb(params
-> start
.sec
, MCDPORT(0));
1364 outb(params
-> start
.frame
, MCDPORT(0));
1365 outb(params
-> end
.min
, MCDPORT(0));
1366 outb(params
-> end
.sec
, MCDPORT(0));
1367 outb(params
-> end
.frame
, MCDPORT(0));
1372 * Timer interrupt routine to test for status ready from the drive.
1373 * (see the next routine)
1377 mcdStatTimer(unsigned long dummy
)
1379 if (!(inb(MCDPORT(1)) & MFL_STATUS
))
1381 wake_up(&mcd_waitq
);
1386 if (McdTimeout
<= 0)
1388 wake_up(&mcd_waitq
);
1392 SET_TIMER(mcdStatTimer
, 1);
1397 * Wait for a status to be returned from the drive. The actual test
1398 * (see routine above) is done by the timer interrupt to avoid
1399 * excessive rescheduling.
1403 getMcdStatus(int timeout
)
1407 McdTimeout
= timeout
;
1408 SET_TIMER(mcdStatTimer
, 1);
1409 sleep_on(&mcd_waitq
);
1410 if (McdTimeout
<= 0)
1413 st
= inb(MCDPORT(0)) & 0xFF;
1417 if ((st
& MST_BUSY
) == 0 && audioStatus
== CDROM_AUDIO_PLAY
)
1418 /* XXX might be an error? look at q-channel? */
1419 audioStatus
= CDROM_AUDIO_COMPLETED
;
1421 if (st
& MST_DSK_CHG
)
1425 audioStatus
= CDROM_AUDIO_NO_STATUS
;
1432 /* gives current state of the drive This function is quite unreliable,
1433 and should probably be rewritten by someone, eventually... */
1434 int mcd_drive_status(struct cdrom_device_info
* cdi
, int slot_nr
)
1438 st
= statusCmd(); /* check drive status */
1440 return -EIO
; /* drive doesn't respond */
1441 if ((st
& MST_READY
)) return CDS_DISC_OK
;
1442 if ((st
& MST_DOOR_OPEN
)) return CDS_TRAY_OPEN
;
1443 if ((st
& MST_DSK_CHG
)) return CDS_NO_DISC
;
1444 if ((st
& MST_BUSY
)) return CDS_DRIVE_NOT_READY
;
1450 * Read a value from the drive.
1454 getValue(unsigned char *result
)
1459 for (count
= 0; count
< 2000; count
++)
1460 if (!(inb(MCDPORT(1)) & MFL_STATUS
))
1465 printk("mcd: getValue timeout\n");
1469 s
= inb(MCDPORT(0)) & 0xFF;
1470 *result
= (unsigned char) s
;
1476 * Read the current Q-channel info. Also used for reading the
1477 * table of contents.
1481 GetQChannelInfo(struct mcd_Toc
*qp
)
1483 unsigned char notUsed
;
1486 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
1488 outb(MCMD_GET_Q_CHANNEL
, MCDPORT(0));
1489 if (getMcdStatus(MCD_STATUS_DELAY
) != -1)
1493 if (retry
>= MCD_RETRY_ATTEMPTS
)
1496 if (getValue(&qp
-> ctrl_addr
) < 0) return -1;
1497 if (getValue(&qp
-> track
) < 0) return -1;
1498 if (getValue(&qp
-> pointIndex
) < 0) return -1;
1499 if (getValue(&qp
-> trackTime
.min
) < 0) return -1;
1500 if (getValue(&qp
-> trackTime
.sec
) < 0) return -1;
1501 if (getValue(&qp
-> trackTime
.frame
) < 0) return -1;
1502 if (getValue(¬Used
) < 0) return -1;
1503 if (getValue(&qp
-> diskTime
.min
) < 0) return -1;
1504 if (getValue(&qp
-> diskTime
.sec
) < 0) return -1;
1505 if (getValue(&qp
-> diskTime
.frame
) < 0) return -1;
1512 * Read the table of contents (TOC) and TOC header if necessary
1521 if (GetDiskInfo() < 0)
1533 * Read the table of contents header
1541 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
1543 outb(MCMD_GET_DISK_INFO
, MCDPORT(0));
1544 if (getMcdStatus(MCD_STATUS_DELAY
) != -1)
1548 if (retry
>= MCD_RETRY_ATTEMPTS
)
1551 if (getValue(&DiskInfo
.first
) < 0) return -1;
1552 if (getValue(&DiskInfo
.last
) < 0) return -1;
1554 DiskInfo
.first
= bcd2bin(DiskInfo
.first
);
1555 DiskInfo
.last
= bcd2bin(DiskInfo
.last
);
1558 printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
1561 DiskInfo
.diskLength
.min
,
1562 DiskInfo
.diskLength
.sec
,
1563 DiskInfo
.diskLength
.frame
,
1564 DiskInfo
.firstTrack
.min
,
1565 DiskInfo
.firstTrack
.sec
,
1566 DiskInfo
.firstTrack
.frame
);
1569 if (getValue(&DiskInfo
.diskLength
.min
) < 0) return -1;
1570 if (getValue(&DiskInfo
.diskLength
.sec
) < 0) return -1;
1571 if (getValue(&DiskInfo
.diskLength
.frame
) < 0) return -1;
1572 if (getValue(&DiskInfo
.firstTrack
.min
) < 0) return -1;
1573 if (getValue(&DiskInfo
.firstTrack
.sec
) < 0) return -1;
1574 if (getValue(&DiskInfo
.firstTrack
.frame
) < 0) return -1;
1581 * Read the table of contents (TOC)
1590 struct mcd_Toc qInfo
;
1592 for (i
= 0; i
< MAX_TRACKS
; i
++)
1593 Toc
[i
].pointIndex
= 0;
1595 i
= DiskInfo
.last
+ 3;
1597 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
1599 outb(MCMD_STOP
, MCDPORT(0));
1600 if (getMcdStatus(MCD_STATUS_DELAY
) != -1)
1604 if (retry
>= MCD_RETRY_ATTEMPTS
)
1607 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
1609 outb(MCMD_SET_MODE
, MCDPORT(0));
1610 outb(0x05, MCDPORT(0)); /* mode: toc */
1612 if (getMcdStatus(MCD_STATUS_DELAY
) != -1)
1616 if (retry
>= MCD_RETRY_ATTEMPTS
)
1619 for (limit
= 300; limit
> 0; limit
--)
1621 if (GetQChannelInfo(&qInfo
) < 0)
1624 px
= bcd2bin(qInfo
.pointIndex
);
1625 if (px
> 0 && px
< MAX_TRACKS
&& qInfo
.track
== 0)
1626 if (Toc
[px
].pointIndex
== 0)
1636 Toc
[DiskInfo
.last
+ 1].diskTime
= DiskInfo
.diskLength
;
1638 for (retry
= 0; retry
< MCD_RETRY_ATTEMPTS
; retry
++)
1640 outb(MCMD_SET_MODE
, MCDPORT(0));
1641 outb(0x01, MCDPORT(0));
1643 if (getMcdStatus(MCD_STATUS_DELAY
) != -1)
1648 for (i
= 1; i
<= DiskInfo
.last
; i
++)
1649 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1650 i
, Toc
[i
].ctrl_addr
, Toc
[i
].track
, Toc
[i
].pointIndex
,
1651 Toc
[i
].trackTime
.min
, Toc
[i
].trackTime
.sec
, Toc
[i
].trackTime
.frame
,
1652 Toc
[i
].diskTime
.min
, Toc
[i
].diskTime
.sec
, Toc
[i
].diskTime
.frame
);
1653 for (i
= 100; i
< 103; i
++)
1654 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1655 i
, Toc
[i
].ctrl_addr
, Toc
[i
].track
, Toc
[i
].pointIndex
,
1656 Toc
[i
].trackTime
.min
, Toc
[i
].trackTime
.sec
, Toc
[i
].trackTime
.frame
,
1657 Toc
[i
].diskTime
.min
, Toc
[i
].diskTime
.sec
, Toc
[i
].diskTime
.frame
);
1660 return limit
> 0 ? 0 : -1;
1664 void __exit
mcd_exit(void)
1667 del_timer_sync(&mcd_timer
);
1671 module_init(mcd_init
);
1673 module_exit(mcd_exit
);