2 linux/kernel/blk_drv/mcd.c - Mitsumi CDROM driver
4 Copyright (C) 1992 Martin Harriss
5 Portions Copyright (C) 2001 Red Hat
7 martin@bdsi.com (no longer valid - where are you now, Martin?)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 0.1 First attempt - internal use only
26 0.2 Cleaned up delays and use of timer - alpha release
27 0.3 Audio support added
28 0.3.1 Changes for mitsumi CRMC LU005S march version
29 (stud11@cc4.kuleuven.ac.be)
30 0.3.2 bug fixes to the ioctls and merged with ALPHA0.99-pl12
31 (Jon Tombs <jon@robots.ox.ac.uk>)
32 0.3.3 Added more #defines and mcd_setup()
33 (Jon Tombs <jon@gtex02.us.es>)
35 October 1993 Bernd Huebner and Ruediger Helsch, Unifix Software GmbH,
36 Braunschweig, Germany: rework to speed up data read operation.
37 Also enabled definition of irq and address from bootstrap, using the
39 November 93 added code for FX001 S,D (single & double speed).
40 February 94 added code for broken M 5/6 series of 16-bit single speed.
44 Added support for loadable MODULEs, so mcd can now also be loaded by
45 insmod and removed by rmmod during runtime.
46 Werner Zimmermann (zimmerma@rz.fht-esslingen.de), Mar. 26, 95
49 I added code for FX001 D to drop from double speed to single speed
50 when encountering errors... this helps with some "problematic" CD's
51 that are supposedly "OUT OF TOLERANCE" (but are really shitty presses!)
52 severely scratched, or possibly slightly warped! I have noticed that
53 the Mitsumi 2x/4x drives are just less tolerant and the firmware is
54 not smart enough to drop speed, so let's just kludge it with software!
55 ****** THE 4X SPEED MITSUMI DRIVES HAVE THE SAME PROBLEM!!!!!! ******
56 Anyone want to "DONATE" one to me?! ;) I hear sometimes they are
58 ** HINT... HINT... TAKE NOTES MITSUMI This could save some hassles with
59 certain "large" CD's that have data on the outside edge in your
60 DOS DRIVERS .... Accuracy counts... speed is secondary ;)
61 17 June 95 Modifications By Andrew J. Kroll <ag784@freenet.buffalo.edu>
62 07 July 1995 Modifications by Andrew J. Kroll
64 Bjorn Ekwall <bj0rn@blox.se> added unregister_blkdev to mcd_init()
66 Michael K. Johnson <johnsonm@redhat.com> added retries on open
67 for slow drives which take a while to recognize that they contain
70 November 1997 -- ported to the Uniform CD-ROM driver by Erik Andersen.
71 March 1999 -- made io base and irq CONFIG_ options (Tigran Aivazian).
73 November 1999 -- Make kernel-parameter implementation work with 2.3.x
74 Removed init_module & cleanup_module in favor of
75 module_init & module_exit.
76 Torben Mathiasen <tmm@image.dk>
78 September 2001 - Reformatted and cleaned up the code
79 Alan Cox <alan@redhat.com>
82 #include <linux/module.h>
84 #include <linux/errno.h>
85 #include <linux/signal.h>
86 #include <linux/sched.h>
88 #include <linux/timer.h>
90 #include <linux/kernel.h>
91 #include <linux/devfs_fs_kernel.h>
92 #include <linux/cdrom.h>
93 #include <linux/ioport.h>
94 #include <linux/string.h>
95 #include <linux/delay.h>
96 #include <linux/init.h>
97 #include <linux/config.h>
99 /* #define REALLY_SLOW_IO */
100 #include <asm/system.h>
102 #include <asm/uaccess.h>
104 #define MAJOR_NR MITSUMI_CDROM_MAJOR
105 #include <linux/blk.h>
107 #define mcd_port mcd /* for compatible parameter passing with "insmod" */
110 static int mcd_blocksizes[1];
113 /* I added A flag to drop to 1x speed if too many errors 0 = 1X ; 1 = 2X */
114 static int mcdDouble;
116 /* How many sectors to hold at 1x speed counter */
117 static int mcd1xhold;
119 /* Is the drive connected properly and responding?? */
120 static int mcdPresent;
122 #define QUICK_LOOP_DELAY udelay(45) /* use udelay */
123 #define QUICK_LOOP_COUNT 20
125 #define CURRENT_VALID \
126 (!QUEUE_EMPTY && MAJOR(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \
127 && CURRENT -> sector != -1)
129 #define MFL_STATUSorDATA (MFL_STATUS | MFL_DATA)
130 #define MCD_BUF_SIZ 16
131 static volatile int mcd_transfer_is_active;
132 static char mcd_buf[2048 * MCD_BUF_SIZ]; /* buffer for block size conversion */
133 static volatile int mcd_buf_bn[MCD_BUF_SIZ], mcd_next_bn;
134 static volatile int mcd_buf_in, mcd_buf_out = -1;
135 static volatile int mcd_error;
136 static int mcd_open_count;
144 MCD_S_STOPPING /* 6 */
146 static volatile enum mcd_state_e mcd_state = MCD_S_IDLE;
147 static int mcd_mode = -1;
148 static int MCMD_DATA_READ = MCMD_PLAY_READ;
150 #define READ_TIMEOUT 3000
152 int mitsumi_bug_93_wait;
154 static short mcd_port = CONFIG_MCD_BASE; /* used as "mcd" by "insmod" */
155 static int mcd_irq = CONFIG_MCD_IRQ; /* must directly follow mcd_port */
156 MODULE_PARM(mcd, "1-2i");
158 static int McdTimeout, McdTries;
159 static DECLARE_WAIT_QUEUE_HEAD(mcd_waitq);
161 static struct mcd_DiskInfo DiskInfo;
162 static struct mcd_Toc Toc[MAX_TRACKS];
163 static struct mcd_Play_msf mcd_Play;
165 static int audioStatus;
166 static char mcdDiskChanged;
167 static char tocUpToDate;
168 static char mcdVersion;
170 static void mcd_transfer(void);
171 static void mcd_poll(unsigned long dummy);
172 static void mcd_invalidate_buffers(void);
173 static void hsg2msf(long hsg, struct msf *msf);
174 static void bin2bcd(unsigned char *p);
175 static int bcd2bin(unsigned char bcd);
176 static int mcdStatus(void);
177 static void sendMcdCmd(int cmd, struct mcd_Play_msf *params);
178 static int getMcdStatus(int timeout);
179 static int GetQChannelInfo(struct mcd_Toc *qp);
180 static int updateToc(void);
181 static int GetDiskInfo(void);
182 static int GetToc(void);
183 static int getValue(unsigned char *result);
184 static int mcd_open(struct cdrom_device_info *cdi, int purpose);
185 static void mcd_release(struct cdrom_device_info *cdi);
186 static int mcd_media_changed(struct cdrom_device_info *cdi, int disc_nr);
187 static int mcd_tray_move(struct cdrom_device_info *cdi, int position);
188 int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
190 int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
192 struct block_device_operations mcd_bdops =
196 release: cdrom_release,
198 check_media_change: cdrom_media_changed,
201 static struct timer_list mcd_timer;
203 static struct cdrom_device_ops mcd_dops = {
206 drive_status:mcd_drive_status,
207 media_changed:mcd_media_changed,
208 tray_move:mcd_tray_move,
209 audio_ioctl:mcd_audio_ioctl,
210 capability:CDC_OPEN_TRAY | CDC_MEDIA_CHANGED |
211 CDC_PLAY_AUDIO | CDC_DRIVE_STATUS,
214 static struct cdrom_device_info mcd_info = {
222 static int __init mcd_setup(char *str)
226 (void) get_options(str, ARRAY_SIZE(ints), ints);
233 mitsumi_bug_93_wait = ints[3];
238 __setup("mcd=", mcd_setup);
242 static int mcd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
249 * Do a 'get status' command and get the result. Only use from the top half
250 * because it calls 'getMcdStatus' which sleeps.
253 static int statusCmd(void)
257 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
258 /* send get-status cmd */
259 outb(MCMD_GET_STATUS, MCDPORT(0));
261 st = getMcdStatus(MCD_STATUS_DELAY);
271 * Send a 'Play' command and get the status. Use only from the top half.
274 static int mcdPlay(struct mcd_Play_msf *arg)
278 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
279 sendMcdCmd(MCMD_PLAY_READ, arg);
280 st = getMcdStatus(2 * MCD_STATUS_DELAY);
289 static int mcd_tray_move(struct cdrom_device_info *cdi, int position)
294 /* all drives can at least stop! */
295 if (audioStatus == CDROM_AUDIO_PLAY) {
296 outb(MCMD_STOP, MCDPORT(0));
297 i = getMcdStatus(MCD_STATUS_DELAY);
300 audioStatus = CDROM_AUDIO_NO_STATUS;
302 outb(MCMD_EJECT, MCDPORT(0));
304 * the status (i) shows failure on all but the FX drives.
305 * But nothing we can do about that in software!
306 * So just read the status and forget it. - Jon.
308 i = getMcdStatus(MCD_STATUS_DELAY);
314 long msf2hsg(struct msf *mp)
316 return bcd2bin(mp->frame) + bcd2bin(mp->sec) * 75 + bcd2bin(mp->min) * 4500 - 150;
320 int mcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
324 struct mcd_Toc qInfo;
326 struct cdrom_tochdr *tocHdr;
327 struct cdrom_msf *msf;
328 struct cdrom_subchnl *subchnl;
329 struct cdrom_tocentry *entry;
330 struct mcd_Toc *tocPtr;
331 struct cdrom_volctrl *volctrl;
340 return i; /* error reading TOC */
344 case CDROMSTART: /* Spin up the drive */
345 /* Don't think we can do this. Even if we could,
346 * I think the drive times out and stops after a while
347 * anyway. For now, ignore it.
352 case CDROMSTOP: /* Spin down the drive */
353 outb(MCMD_STOP, MCDPORT(0));
354 i = getMcdStatus(MCD_STATUS_DELAY);
356 /* should we do anything if it fails? */
358 audioStatus = CDROM_AUDIO_NO_STATUS;
361 case CDROMPAUSE: /* Pause the drive */
362 if (audioStatus != CDROM_AUDIO_PLAY)
365 outb(MCMD_STOP, MCDPORT(0));
366 i = getMcdStatus(MCD_STATUS_DELAY);
368 if (GetQChannelInfo(&qInfo) < 0) {
369 /* didn't get q channel info */
371 audioStatus = CDROM_AUDIO_NO_STATUS;
375 mcd_Play.start = qInfo.diskTime; /* remember restart point */
377 audioStatus = CDROM_AUDIO_PAUSED;
380 case CDROMRESUME: /* Play it again, Sam */
381 if (audioStatus != CDROM_AUDIO_PAUSED)
384 /* restart the drive at the saved position. */
386 i = mcdPlay(&mcd_Play);
388 audioStatus = CDROM_AUDIO_ERROR;
392 audioStatus = CDROM_AUDIO_PLAY;
395 case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
397 ti = (struct cdrom_ti *) arg;
399 if (ti->cdti_trk0 < DiskInfo.first
400 || ti->cdti_trk0 > DiskInfo.last
401 || ti->cdti_trk1 < ti->cdti_trk0) {
405 if (ti->cdti_trk1 > DiskInfo.last)
406 ti->cdti_trk1 = DiskInfo.last;
408 mcd_Play.start = Toc[ti->cdti_trk0].diskTime;
409 mcd_Play.end = Toc[ti->cdti_trk1 + 1].diskTime;
412 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
413 mcd_Play.start.min, mcd_Play.start.sec,
414 mcd_Play.start.frame, mcd_Play.end.min,
415 mcd_Play.end.sec, mcd_Play.end.frame);
418 i = mcdPlay(&mcd_Play);
420 audioStatus = CDROM_AUDIO_ERROR;
424 audioStatus = CDROM_AUDIO_PLAY;
427 case CDROMPLAYMSF: /* Play starting at the given MSF address. */
429 if (audioStatus == CDROM_AUDIO_PLAY) {
430 outb(MCMD_STOP, MCDPORT(0));
431 i = getMcdStatus(MCD_STATUS_DELAY);
432 audioStatus = CDROM_AUDIO_NO_STATUS;
435 msf = (struct cdrom_msf *) arg;
439 bin2bcd(&msf->cdmsf_min0);
440 bin2bcd(&msf->cdmsf_sec0);
441 bin2bcd(&msf->cdmsf_frame0);
442 bin2bcd(&msf->cdmsf_min1);
443 bin2bcd(&msf->cdmsf_sec1);
444 bin2bcd(&msf->cdmsf_frame1);
446 mcd_Play.start.min = msf->cdmsf_min0;
447 mcd_Play.start.sec = msf->cdmsf_sec0;
448 mcd_Play.start.frame = msf->cdmsf_frame0;
449 mcd_Play.end.min = msf->cdmsf_min1;
450 mcd_Play.end.sec = msf->cdmsf_sec1;
451 mcd_Play.end.frame = msf->cdmsf_frame1;
454 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
455 mcd_Play.start.min, mcd_Play.start.sec,
456 mcd_Play.start.frame, mcd_Play.end.min,
457 mcd_Play.end.sec, mcd_Play.end.frame);
460 i = mcdPlay(&mcd_Play);
462 audioStatus = CDROM_AUDIO_ERROR;
466 audioStatus = CDROM_AUDIO_PLAY;
469 case CDROMREADTOCHDR: /* Read the table of contents header */
470 tocHdr = (struct cdrom_tochdr *) arg;
471 tocHdr->cdth_trk0 = DiskInfo.first;
472 tocHdr->cdth_trk1 = DiskInfo.last;
475 case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
476 entry = (struct cdrom_tocentry *) arg;
477 if (entry->cdte_track == CDROM_LEADOUT)
478 tocPtr = &Toc[DiskInfo.last - DiskInfo.first + 1];
480 else if (entry->cdte_track > DiskInfo.last
481 || entry->cdte_track < DiskInfo.first)
485 tocPtr = &Toc[entry->cdte_track];
487 entry->cdte_adr = tocPtr->ctrl_addr;
488 entry->cdte_ctrl = tocPtr->ctrl_addr >> 4;
490 if (entry->cdte_format == CDROM_LBA)
491 entry->cdte_addr.lba = msf2hsg(&tocPtr->diskTime);
493 else if (entry->cdte_format == CDROM_MSF) {
494 entry->cdte_addr.msf.minute =
495 bcd2bin(tocPtr->diskTime.min);
496 entry->cdte_addr.msf.second =
497 bcd2bin(tocPtr->diskTime.sec);
498 entry->cdte_addr.msf.frame =
499 bcd2bin(tocPtr->diskTime.frame);
507 case CDROMSUBCHNL: /* Get subchannel info */
509 subchnl = (struct cdrom_subchnl *) arg;
510 if (GetQChannelInfo(&qInfo) < 0)
513 subchnl->cdsc_audiostatus = audioStatus;
514 subchnl->cdsc_adr = qInfo.ctrl_addr;
515 subchnl->cdsc_ctrl = qInfo.ctrl_addr >> 4;
516 subchnl->cdsc_trk = bcd2bin(qInfo.track);
517 subchnl->cdsc_ind = bcd2bin(qInfo.pointIndex);
518 subchnl->cdsc_absaddr.msf.minute = bcd2bin(qInfo.diskTime.min);
519 subchnl->cdsc_absaddr.msf.second = bcd2bin(qInfo.diskTime.sec);
520 subchnl->cdsc_absaddr.msf.frame = bcd2bin(qInfo.diskTime.frame);
521 subchnl->cdsc_reladdr.msf.minute = bcd2bin(qInfo.trackTime.min);
522 subchnl->cdsc_reladdr.msf.second = bcd2bin(qInfo.trackTime.sec);
523 subchnl->cdsc_reladdr.msf.frame = bcd2bin(qInfo.trackTime.frame);
526 case CDROMVOLCTRL: /* Volume control */
527 volctrl = (struct cdrom_volctrl *) arg;
528 outb(MCMD_SET_VOLUME, MCDPORT(0));
529 outb(volctrl->channel0, MCDPORT(0));
530 outb(255, MCDPORT(0));
531 outb(volctrl->channel1, MCDPORT(0));
532 outb(255, MCDPORT(0));
534 i = getMcdStatus(MCD_STATUS_DELAY);
555 * Take care of the different block sizes between cdrom and Linux.
556 * When Linux gets variable block sizes this will probably go away.
559 static void mcd_transfer(void)
562 while (CURRENT->nr_sectors) {
563 int bn = CURRENT->sector / 4;
565 for (i = 0; i < MCD_BUF_SIZ && mcd_buf_bn[i] != bn;
567 if (i < MCD_BUF_SIZ) {
568 int offs =(i * 4 + (CURRENT->sector & 3)) * 512;
569 int nr_sectors = 4 - (CURRENT->sector & 3);
570 if (mcd_buf_out != i) {
572 if (mcd_buf_bn[i] != bn) {
577 if (nr_sectors > CURRENT->nr_sectors)
578 nr_sectors = CURRENT->nr_sectors;
579 memcpy(CURRENT->buffer, mcd_buf + offs,
581 CURRENT->nr_sectors -= nr_sectors;
582 CURRENT->sector += nr_sectors;
583 CURRENT->buffer += nr_sectors * 512;
594 * We only seem to get interrupts after an error.
595 * Just take the interrupt and clear out the status reg.
598 static void mcd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
602 st = inb(MCDPORT(1)) & 0xFF;
603 test1(printk("<int1-%02X>", st));
604 if (!(st & MFL_STATUS)) {
605 st = inb(MCDPORT(0)) & 0xFF;
606 test1(printk("<int0-%02X>", st));
607 if ((st & 0xFF) != 0xFF)
608 mcd_error = st ? st & 0xFF : -1;
613 static void do_mcd_request(request_queue_t * q)
615 test2(printk(" do_mcd_request(%ld+%ld)\n", CURRENT->sector,
616 CURRENT->nr_sectors));
618 mcd_transfer_is_active = 1;
619 while (CURRENT_VALID) {
621 if (!buffer_locked(CURRENT->bh))
622 panic(DEVICE_NAME ": block not locked");
625 if (CURRENT->nr_sectors == 0) {
628 mcd_buf_out = -1; /* Want to read a block not in buffer */
629 if (mcd_state == MCD_S_IDLE) {
631 if (updateToc() < 0) {
632 while (CURRENT_VALID)
637 mcd_state = MCD_S_START;
639 mcd_timer.function = mcd_poll;
640 mod_timer(&mcd_timer, jiffies + 1);
645 mcd_transfer_is_active = 0;
646 test2(printk(" do_mcd_request ends\n"));
651 static void mcd_poll(unsigned long dummy)
657 if (mcd_error & 0xA5) {
658 printk(KERN_ERR "mcd: I/O error 0x%02x", mcd_error);
659 if (mcd_error & 0x80)
660 printk(" (Door open)");
661 if (mcd_error & 0x20)
662 printk(" (Disk changed)");
663 if (mcd_error & 0x04) {
664 printk(" (Read error)"); /* Bitch about the problem. */
666 /* Time to get fancy! If at 2x speed and 1 error, drop to 1x speed! */
667 /* Interesting how it STAYS at MCD_RETRY_ATTEMPTS on first error! */
668 /* But I find that rather HANDY!!! */
669 /* Neat! it REALLY WORKS on those LOW QUALITY CD's!!! Smile! :) */
672 /* Slap the CD down to single speed! */
674 && McdTries == MCD_RETRY_ATTEMPTS
675 && MCMD_DATA_READ == MCMD_2X_READ) {
676 MCMD_DATA_READ = MCMD_PLAY_READ; /* Uhhh, Ummmm, muhuh-huh! */
677 mcd1xhold = SINGLE_HOLD_SECTORS; /* Hey Beavis! */
678 printk(" Speed now 1x"); /* Pull my finger! */
682 mcd_invalidate_buffers();
683 #ifdef WARN_IF_READ_FAILURE
684 if (McdTries == MCD_RETRY_ATTEMPTS)
685 printk(KERN_ERR "mcd: read of block %d failed\n",
689 /* Nuts! This cd is ready for recycling! */
690 /* When WAS the last time YOU cleaned it CORRECTLY?! */
691 printk(KERN_ERR "mcd: read of block %d failed, giving up\n",
693 if (mcd_transfer_is_active) {
699 McdTries = MCD_RETRY_ATTEMPTS;
703 mcd_state = MCD_S_STOP;
705 /* Switch back to Double speed if enough GOOD sectors were read! */
707 /* Are we a double speed with a crappy CD?! */
708 if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS
709 && MCMD_DATA_READ == MCMD_PLAY_READ) {
710 /* We ARE a double speed and we ARE bitching! */
711 if (mcd1xhold == 0) { /* Okay, Like are we STILL at single speed? *//* We need to switch back to double speed now... */
712 MCMD_DATA_READ = MCMD_2X_READ; /* Uhhh... BACK You GO! */
713 printk(KERN_INFO "mcd: Switching back to 2X speed!\n"); /* Tell 'em! */
715 mcd1xhold--; /* No?! Count down the good reads some more... */
716 /* and try, try again! */
722 test3(printk("MCD_S_IDLE\n"));
726 test3(printk("MCD_S_START\n"));
727 outb(MCMD_GET_STATUS, MCDPORT(0));
728 mcd_state = mcd_mode == 1 ? MCD_S_READ : MCD_S_MODE;
733 test3(printk("MCD_S_MODE\n"));
734 if ((st = mcdStatus()) != -1) {
735 if (st & MST_DSK_CHG) {
738 mcd_invalidate_buffers();
741 set_mode_immediately:
742 if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {
745 if (mcd_transfer_is_active) {
746 mcd_state = MCD_S_START;
750 printk((st & MST_DOOR_OPEN) ?
752 "mcd: disk removed\n");
753 mcd_state = MCD_S_IDLE;
754 while (CURRENT_VALID)
758 outb(MCMD_SET_MODE, MCDPORT(0));
761 mcd_state = MCD_S_READ;
767 test3(printk("MCD_S_READ\n"));
768 if ((st = mcdStatus()) != -1) {
769 if (st & MST_DSK_CHG) {
772 mcd_invalidate_buffers();
776 if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {
779 if (mcd_transfer_is_active) {
780 mcd_state = MCD_S_START;
784 printk((st & MST_DOOR_OPEN) ?
786 "mcd: disk removed\n");
787 mcd_state = MCD_S_IDLE;
788 while (CURRENT_VALID)
794 struct mcd_Play_msf msf;
795 mcd_next_bn = CURRENT->sector / 4;
796 hsg2msf(mcd_next_bn, &msf.start);
800 sendMcdCmd(MCMD_DATA_READ, &msf);
801 mcd_state = MCD_S_DATA;
802 McdTimeout = READ_TIMEOUT;
804 mcd_state = MCD_S_STOP;
812 test3(printk("MCD_S_DATA\n"));
813 st = inb(MCDPORT(1)) & (MFL_STATUSorDATA);
815 test5(printk("Status %02x\n", st))
818 #ifdef WARN_IF_READ_FAILURE
820 printk(KERN_WARNING "mcd: read of block %d failed\n",
824 printk(KERN_ERR "mcd: read of block %d failed, giving up\n", mcd_next_bn);
825 if (mcd_transfer_is_active) {
833 mcd_state = MCD_S_START;
834 McdTimeout = READ_TIMEOUT;
837 case MFL_STATUSorDATA:
842 if (!CURRENT_VALID && mcd_buf_in == mcd_buf_out) {
843 mcd_state = MCD_S_STOP;
846 mcd_buf_bn[mcd_buf_in] = -1;
847 insb(MCDPORT(0), mcd_buf + 2048 * mcd_buf_in,
849 mcd_buf_bn[mcd_buf_in] = mcd_next_bn++;
850 if (mcd_buf_out == -1)
851 mcd_buf_out = mcd_buf_in;
852 mcd_buf_in = mcd_buf_in + 1 == MCD_BUF_SIZ ? 0 : mcd_buf_in + 1;
853 if (!mcd_transfer_is_active) {
854 while (CURRENT_VALID) {
856 if (CURRENT->nr_sectors == 0)
864 && (CURRENT->sector / 4 < mcd_next_bn ||
865 CURRENT->sector / 4 > mcd_next_bn + 16)) {
866 mcd_state = MCD_S_STOP;
869 McdTimeout = READ_TIMEOUT;
871 int count = QUICK_LOOP_COUNT;
874 if ((st = (inb(MCDPORT(1))) & (MFL_STATUSorDATA)) != (MFL_STATUSorDATA)) {
875 test4(printk(" %d ", QUICK_LOOP_COUNT - count));
876 goto data_immediately;
879 test4(printk("ended "));
886 test3(printk("MCD_S_STOP\n"));
887 if (!mitsumi_bug_93_wait)
888 goto do_not_work_around_mitsumi_bug_93_1;
890 McdTimeout = mitsumi_bug_93_wait;
891 mcd_state = 9 + 3 + 1;
898 do_not_work_around_mitsumi_bug_93_1:
899 outb(MCMD_STOP, MCDPORT(0));
900 if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {
904 } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);
905 outb(MCMD_STOP, MCDPORT(0));
906 if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {
910 } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);
911 outb(MCMD_STOP, MCDPORT(0));
915 mcd_state = MCD_S_STOPPING;
920 test3(printk("MCD_S_STOPPING\n"));
921 if ((st = mcdStatus()) == -1 && McdTimeout)
924 if ((st != -1) && (st & MST_DSK_CHG)) {
927 mcd_invalidate_buffers();
929 if (!mitsumi_bug_93_wait)
930 goto do_not_work_around_mitsumi_bug_93_2;
932 McdTimeout = mitsumi_bug_93_wait;
933 mcd_state = 9 + 3 + 2;
941 do_not_work_around_mitsumi_bug_93_2:
942 test3(printk("CURRENT_VALID %d mcd_mode %d\n", CURRENT_VALID, mcd_mode));
946 goto read_immediately;
948 goto set_mode_immediately;
950 mcd_state = MCD_S_START;
954 mcd_state = MCD_S_IDLE;
959 printk(KERN_ERR "mcd: invalid state %d\n", mcd_state);
964 printk(KERN_WARNING "mcd: timeout in state %d\n", mcd_state);
965 mcd_state = MCD_S_STOP;
967 mcd_timer.function = mcd_poll;
968 mod_timer(&mcd_timer, jiffies + 1);
973 static void mcd_invalidate_buffers(void)
976 for (i = 0; i < MCD_BUF_SIZ; ++i)
982 * Open the device special file. Check that a disk is in.
984 static int mcd_open(struct cdrom_device_info *cdi, int purpose)
988 return -ENXIO; /* no hardware */
990 if (mcd_open_count || mcd_state != MCD_S_IDLE)
993 mcd_invalidate_buffers();
995 st = statusCmd(); /* check drive status */
997 goto err_out; /* drive doesn't respond */
998 if ((st & MST_READY) == 0) { /* no disk? wait a sec... */
999 current->state = TASK_INTERRUPTIBLE;
1000 schedule_timeout(HZ);
1002 } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);
1004 if (updateToc() < 0)
1017 * On close, we flush all mcd blocks from the buffer cache.
1019 static void mcd_release(struct cdrom_device_info *cdi)
1021 if (!--mcd_open_count) {
1022 mcd_invalidate_buffers();
1028 /* This routine gets called during initialization if things go wrong,
1029 * and is used in mcd_exit as well. */
1030 static void cleanup(int level)
1034 if (unregister_cdrom(&mcd_info)) {
1035 printk(KERN_WARNING "Can't unregister cdrom mcd\n");
1038 free_irq(mcd_irq, NULL);
1040 release_region(mcd_port, 4);
1042 if (devfs_unregister_blkdev(MAJOR_NR, "mcd")) {
1043 printk(KERN_WARNING "Can't unregister major mcd\n");
1046 blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
1054 * Test for presence of drive and initialize it. Called at boot time.
1057 int __init mcd_init(void)
1060 unsigned char result[3];
1063 if (mcd_port <= 0 || mcd_irq <= 0) {
1064 printk(KERN_INFO "mcd: not probing.\n");
1068 if (devfs_register_blkdev(MAJOR_NR, "mcd", &mcd_bdops) != 0) {
1069 printk(KERN_ERR "mcd: Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR);
1072 if (check_region(mcd_port, 4)) {
1074 printk(KERN_ERR "mcd: Initialization failed, I/O port (%X) already in use\n", mcd_port);
1078 blksize_size[MAJOR_NR] = mcd_blocksizes;
1079 blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
1080 read_ahead[MAJOR_NR] = 4;
1082 /* check for card */
1084 outb(0, MCDPORT(1)); /* send reset */
1085 for (count = 0; count < 2000000; count++)
1086 (void) inb(MCDPORT(1)); /* delay a bit */
1088 outb(0x40, MCDPORT(0)); /* send get-stat cmd */
1089 for (count = 0; count < 2000000; count++)
1090 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1093 if (count >= 2000000) {
1094 printk(KERN_INFO "mcd: initialisation failed - No mcd device at 0x%x irq %d\n",
1099 count = inb(MCDPORT(0)); /* pick up the status */
1101 outb(MCMD_GET_VERSION, MCDPORT(0));
1102 for (count = 0; count < 3; count++)
1103 if (getValue(result + count)) {
1104 printk(KERN_ERR "mcd: mitsumi get version failed at 0x%x\n",
1110 if (result[0] == result[1] && result[1] == result[2]) {
1115 mcdVersion = result[2];
1117 if (mcdVersion >= 4)
1118 outb(4, MCDPORT(2)); /* magic happens */
1120 /* don't get the IRQ until we know for sure the drive is there */
1122 if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD", NULL)) {
1123 printk(KERN_ERR "mcd: Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
1128 if (result[1] == 'D') {
1129 MCMD_DATA_READ = MCMD_2X_READ;
1130 /* Added flag to drop to 1x speed if too many errors */
1134 sprintf(msg, " mcd: Mitsumi %s Speed CD-ROM at port=0x%x,"
1135 " irq=%d\n", mcd_info.speed == 1 ? "Single" : "Double",
1138 request_region(mcd_port, 4, "mcd");
1140 outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
1141 outb(0x02, MCDPORT(0));
1142 outb(0x00, MCDPORT(0));
1145 outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
1146 outb(0x10, MCDPORT(0));
1147 outb(0x04, MCDPORT(0));
1150 mcd_invalidate_buffers();
1153 mcd_info.dev = MKDEV(MAJOR_NR, 0);
1155 if (register_cdrom(&mcd_info) != 0) {
1156 printk(KERN_ERR "mcd: Unable to register Mitsumi CD-ROM.\n");
1160 devfs_plain_cdrom(&mcd_info, &mcd_bdops);
1167 static void hsg2msf(long hsg, struct msf *msf)
1170 msf->min = hsg / 4500;
1172 msf->sec = hsg / 75;
1173 msf->frame = hsg % 75;
1175 bin2bcd(&msf->min); /* convert to BCD */
1177 bin2bcd(&msf->frame);
1181 static void bin2bcd(unsigned char *p)
1190 static int bcd2bin(unsigned char bcd)
1192 return (bcd >> 4) * 10 + (bcd & 0xF);
1197 * See if a status is ready from the drive and return it
1201 static int mcdStatus(void)
1206 st = inb(MCDPORT(1)) & MFL_STATUS;
1208 i = inb(MCDPORT(0)) & 0xFF;
1216 * Send a play or read command to the drive
1219 static void sendMcdCmd(int cmd, struct mcd_Play_msf *params)
1221 outb(cmd, MCDPORT(0));
1222 outb(params->start.min, MCDPORT(0));
1223 outb(params->start.sec, MCDPORT(0));
1224 outb(params->start.frame, MCDPORT(0));
1225 outb(params->end.min, MCDPORT(0));
1226 outb(params->end.sec, MCDPORT(0));
1227 outb(params->end.frame, MCDPORT(0));
1232 * Timer interrupt routine to test for status ready from the drive.
1233 * (see the next routine)
1236 static void mcdStatTimer(unsigned long dummy)
1238 if (!(inb(MCDPORT(1)) & MFL_STATUS)) {
1239 wake_up(&mcd_waitq);
1244 if (McdTimeout <= 0) {
1245 wake_up(&mcd_waitq);
1248 mcd_timer.function = mcdStatTimer;
1249 mod_timer(&mcd_timer, jiffies + 1);
1254 * Wait for a status to be returned from the drive. The actual test
1255 * (see routine above) is done by the timer interrupt to avoid
1256 * excessive rescheduling.
1259 static int getMcdStatus(int timeout)
1263 McdTimeout = timeout;
1264 mcd_timer.function = mcdStatTimer;
1265 mod_timer(&mcd_timer, jiffies + 1);
1266 sleep_on(&mcd_waitq);
1267 if (McdTimeout <= 0)
1270 st = inb(MCDPORT(0)) & 0xFF;
1274 if ((st & MST_BUSY) == 0 && audioStatus == CDROM_AUDIO_PLAY)
1275 /* XXX might be an error? look at q-channel? */
1276 audioStatus = CDROM_AUDIO_COMPLETED;
1278 if (st & MST_DSK_CHG) {
1281 audioStatus = CDROM_AUDIO_NO_STATUS;
1288 /* gives current state of the drive This function is quite unreliable,
1289 and should probably be rewritten by someone, eventually... */
1291 int mcd_drive_status(struct cdrom_device_info *cdi, int slot_nr)
1295 st = statusCmd(); /* check drive status */
1297 return -EIO; /* drive doesn't respond */
1298 if ((st & MST_READY))
1300 if ((st & MST_DOOR_OPEN))
1301 return CDS_TRAY_OPEN;
1302 if ((st & MST_DSK_CHG))
1304 if ((st & MST_BUSY))
1305 return CDS_DRIVE_NOT_READY;
1311 * Read a value from the drive.
1314 static int getValue(unsigned char *result)
1319 for (count = 0; count < 2000; count++)
1320 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1323 if (count >= 2000) {
1324 printk("mcd: getValue timeout\n");
1328 s = inb(MCDPORT(0)) & 0xFF;
1329 *result = (unsigned char) s;
1334 * Read the current Q-channel info. Also used for reading the
1335 * table of contents.
1338 int GetQChannelInfo(struct mcd_Toc *qp)
1340 unsigned char notUsed;
1343 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
1344 outb(MCMD_GET_Q_CHANNEL, MCDPORT(0));
1345 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1349 if (retry >= MCD_RETRY_ATTEMPTS)
1352 if (getValue(&qp->ctrl_addr) < 0)
1354 if (getValue(&qp->track) < 0)
1356 if (getValue(&qp->pointIndex) < 0)
1358 if (getValue(&qp->trackTime.min) < 0)
1360 if (getValue(&qp->trackTime.sec) < 0)
1362 if (getValue(&qp->trackTime.frame) < 0)
1364 if (getValue(¬Used) < 0)
1366 if (getValue(&qp->diskTime.min) < 0)
1368 if (getValue(&qp->diskTime.sec) < 0)
1370 if (getValue(&qp->diskTime.frame) < 0)
1377 * Read the table of contents (TOC) and TOC header if necessary
1380 static int updateToc(void)
1385 if (GetDiskInfo() < 0)
1396 * Read the table of contents header
1399 static int GetDiskInfo(void)
1403 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
1404 outb(MCMD_GET_DISK_INFO, MCDPORT(0));
1405 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1409 if (retry >= MCD_RETRY_ATTEMPTS)
1412 if (getValue(&DiskInfo.first) < 0)
1414 if (getValue(&DiskInfo.last) < 0)
1417 DiskInfo.first = bcd2bin(DiskInfo.first);
1418 DiskInfo.last = bcd2bin(DiskInfo.last);
1422 ("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
1423 DiskInfo.first, DiskInfo.last, DiskInfo.diskLength.min,
1424 DiskInfo.diskLength.sec, DiskInfo.diskLength.frame,
1425 DiskInfo.firstTrack.min, DiskInfo.firstTrack.sec,
1426 DiskInfo.firstTrack.frame);
1429 if (getValue(&DiskInfo.diskLength.min) < 0)
1431 if (getValue(&DiskInfo.diskLength.sec) < 0)
1433 if (getValue(&DiskInfo.diskLength.frame) < 0)
1435 if (getValue(&DiskInfo.firstTrack.min) < 0)
1437 if (getValue(&DiskInfo.firstTrack.sec) < 0)
1439 if (getValue(&DiskInfo.firstTrack.frame) < 0)
1446 * Read the table of contents (TOC)
1449 static int GetToc(void)
1454 struct mcd_Toc qInfo;
1456 for (i = 0; i < MAX_TRACKS; i++)
1457 Toc[i].pointIndex = 0;
1459 i = DiskInfo.last + 3;
1461 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
1462 outb(MCMD_STOP, MCDPORT(0));
1463 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1467 if (retry >= MCD_RETRY_ATTEMPTS)
1470 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
1471 outb(MCMD_SET_MODE, MCDPORT(0));
1472 outb(0x05, MCDPORT(0)); /* mode: toc */
1474 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1478 if (retry >= MCD_RETRY_ATTEMPTS)
1481 for (limit = 300; limit > 0; limit--) {
1482 if (GetQChannelInfo(&qInfo) < 0)
1485 px = bcd2bin(qInfo.pointIndex);
1486 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
1487 if (Toc[px].pointIndex == 0) {
1496 Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
1498 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++) {
1499 outb(MCMD_SET_MODE, MCDPORT(0));
1500 outb(0x01, MCDPORT(0));
1502 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1507 for (i = 1; i <= DiskInfo.last; i++)
1509 ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1510 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1511 Toc[i].trackTime.min, Toc[i].trackTime.sec,
1512 Toc[i].trackTime.frame, Toc[i].diskTime.min,
1513 Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1514 for (i = 100; i < 103; i++)
1516 ("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1517 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1518 Toc[i].trackTime.min, Toc[i].trackTime.sec,
1519 Toc[i].trackTime.frame, Toc[i].diskTime.min,
1520 Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1523 return limit > 0 ? 0 : -1;
1526 void __exit mcd_exit(void)
1529 del_timer_sync(&mcd_timer);
1533 module_init(mcd_init);
1535 module_exit(mcd_exit);
1537 MODULE_AUTHOR("Martin Harriss");
1538 MODULE_LICENSE("GPL");