This source file includes following definitions.
- mcd_setup
- check_mcd_change
- statusCmd
- mcdPlay
- msf2hsg
- mcd_ioctl
- mcd_transfer
- mcd_interrupt
- do_mcd_request
- mcd_poll
- mcd_invalidate_buffers
- mcd_open
- mcd_release
- mcd_init
- hsg2msf
- bin2bcd
- bcd2bin
- mcdStatus
- sendMcdCmd
- mcdStatTimer
- getMcdStatus
- getValue
- GetQChannelInfo
- updateToc
- GetDiskInfo
- GetToc
- cleanup_module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 #include <linux/config.h>
66
67 #ifdef MODULE
68 # include <linux/module.h>
69 # include <linux/version.h>
70 # ifndef CONFIG_MODVERSIONS
71 char kernel_version[]= UTS_RELEASE;
72 # endif
73 #define mcd_init init_module
74 #else
75 # define MOD_INC_USE_COUNT
76 # define MOD_DEC_USE_COUNT
77 #endif
78
79 #include <linux/errno.h>
80 #include <linux/signal.h>
81 #include <linux/sched.h>
82 #include <linux/mm.h>
83 #include <linux/timer.h>
84 #include <linux/fs.h>
85 #include <linux/kernel.h>
86 #include <linux/cdrom.h>
87 #include <linux/ioport.h>
88 #include <linux/string.h>
89 #include <linux/delay.h>
90
91
92 #include <asm/system.h>
93 #include <asm/io.h>
94 #include <asm/segment.h>
95
96 #define MAJOR_NR MITSUMI_CDROM_MAJOR
97 #include <linux/blk.h>
98 #define mcd_port mcd
99 #include <linux/mcd.h>
100
101 #if 0
102 static int mcd_sizes[] = { 0 };
103 #endif
104
105
106
107
108
109
110
111
112 #define SINGLE_HOLD_SECTORS 30
113
114 #define MCMD_2X_READ 0xC1
115
116
117 static int mcdDouble = 0;
118
119
120 static int mcd1xhold = 0;
121
122
123 static int mcdPresent = 0;
124
125 #if 0
126 #define TEST1
127 #define TEST2
128 #define TEST3 */
129 #define TEST4
130 #define TEST5 */
131 #endif
132
133 #if 1
134 #define QUICK_LOOP_DELAY udelay(45)
135 #define QUICK_LOOP_COUNT 20
136 #else
137 #define QUICK_LOOP_DELAY
138 #define QUICK_LOOP_COUNT 140
139 #endif
140
141
142 #define CURRENT_VALID \
143 (CURRENT && MAJOR(CURRENT -> rq_dev) == MAJOR_NR && CURRENT -> cmd == READ \
144 && CURRENT -> sector != -1)
145 #define MFL_STATUSorDATA (MFL_STATUS | MFL_DATA)
146 #define MCD_BUF_SIZ 16
147 static volatile int mcd_transfer_is_active;
148 static char mcd_buf[2048*MCD_BUF_SIZ];
149 static volatile int mcd_buf_bn[MCD_BUF_SIZ], mcd_next_bn;
150 static volatile int mcd_buf_in, mcd_buf_out = -1;
151 static volatile int mcd_error;
152 static int mcd_open_count;
153 enum mcd_state_e {
154 MCD_S_IDLE,
155 MCD_S_START,
156 MCD_S_MODE,
157 MCD_S_READ,
158 MCD_S_DATA,
159 MCD_S_STOP,
160 MCD_S_STOPPING
161 };
162 static volatile enum mcd_state_e mcd_state = MCD_S_IDLE;
163 static int mcd_mode = -1;
164 static int MCMD_DATA_READ= MCMD_PLAY_READ;
165 #define READ_TIMEOUT 3000
166 #define WORK_AROUND_MITSUMI_BUG_92
167 #define WORK_AROUND_MITSUMI_BUG_93
168 #ifdef WORK_AROUND_MITSUMI_BUG_93
169 int mitsumi_bug_93_wait = 0;
170 #endif
171
172 static short mcd_port = MCD_BASE_ADDR;
173 static int mcd_irq = MCD_INTR_NR;
174
175 static int McdTimeout, McdTries;
176 static struct wait_queue *mcd_waitq = NULL;
177
178 static struct mcd_DiskInfo DiskInfo;
179 static struct mcd_Toc Toc[MAX_TRACKS];
180 static struct mcd_Play_msf mcd_Play;
181
182 static int audioStatus;
183 static char mcdDiskChanged;
184 static char tocUpToDate;
185 static char mcdVersion;
186
187 static void mcd_transfer(void);
188 static void mcd_poll(void);
189 static void mcd_invalidate_buffers(void);
190 static void hsg2msf(long hsg, struct msf *msf);
191 static void bin2bcd(unsigned char *p);
192 static int bcd2bin(unsigned char bcd);
193 static int mcdStatus(void);
194 static void sendMcdCmd(int cmd, struct mcd_Play_msf *params);
195 static int getMcdStatus(int timeout);
196 static int GetQChannelInfo(struct mcd_Toc *qp);
197 static int updateToc(void);
198 static int GetDiskInfo(void);
199 static int GetToc(void);
200 static int getValue(unsigned char *result);
201
202
203 void mcd_setup(char *str, int *ints)
204 {
205 if (ints[0] > 0)
206 mcd_port = ints[1];
207 if (ints[0] > 1)
208 mcd_irq = ints[2];
209 #ifdef WORK_AROUND_MITSUMI_BUG_93
210 if (ints[0] > 2)
211 mitsumi_bug_93_wait = ints[3];
212 #endif
213 }
214
215
216 static int
217 check_mcd_change(kdev_t full_dev)
218 {
219 int retval, target;
220
221
222 #if 1
223 return 0;
224 #endif
225 target = MINOR(full_dev);
226
227 if (target > 0) {
228 printk("mcd: Mitsumi CD-ROM request error: invalid device.\n");
229 return 0;
230 }
231
232 retval = mcdDiskChanged;
233 mcdDiskChanged = 0;
234
235 return retval;
236 }
237
238
239
240
241
242
243
244 static int
245 statusCmd(void)
246 {
247 int st, retry;
248
249 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
250 {
251
252 outb(MCMD_GET_STATUS, MCDPORT(0));
253 st = getMcdStatus(MCD_STATUS_DELAY);
254 if (st != -1)
255 break;
256 }
257
258 return st;
259 }
260
261
262
263
264
265
266 static int
267 mcdPlay(struct mcd_Play_msf *arg)
268 {
269 int retry, st;
270
271 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
272 {
273 sendMcdCmd(MCMD_PLAY_READ, arg);
274 st = getMcdStatus(2 * MCD_STATUS_DELAY);
275 if (st != -1)
276 break;
277 }
278
279 return st;
280 }
281
282
283 long
284 msf2hsg(struct msf *mp)
285 {
286 return bcd2bin(mp -> frame)
287 + bcd2bin(mp -> sec) * 75
288 + bcd2bin(mp -> min) * 4500
289 - 150;
290 }
291
292
293 static int
294 mcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
295 unsigned long arg)
296 {
297 int i, st;
298 struct mcd_Toc qInfo;
299 struct cdrom_ti ti;
300 struct cdrom_tochdr tocHdr;
301 struct cdrom_msf msf;
302 struct cdrom_tocentry entry;
303 struct mcd_Toc *tocPtr;
304 struct cdrom_subchnl subchnl;
305 struct cdrom_volctrl volctrl;
306
307 if (!ip)
308 return -EINVAL;
309
310 st = statusCmd();
311 if (st < 0)
312 return -EIO;
313
314 if (!tocUpToDate)
315 {
316 i = updateToc();
317 if (i < 0)
318 return i;
319 }
320
321 switch (cmd)
322 {
323 case CDROMSTART:
324
325
326
327
328
329 return 0;
330
331 case CDROMSTOP:
332 outb(MCMD_STOP, MCDPORT(0));
333 i = getMcdStatus(MCD_STATUS_DELAY);
334
335
336
337 audioStatus = CDROM_AUDIO_NO_STATUS;
338 return 0;
339
340 case CDROMPAUSE:
341 if (audioStatus != CDROM_AUDIO_PLAY)
342 return -EINVAL;
343
344 outb(MCMD_STOP, MCDPORT(0));
345 i = getMcdStatus(MCD_STATUS_DELAY);
346
347 if (GetQChannelInfo(&qInfo) < 0)
348 {
349
350
351 audioStatus = CDROM_AUDIO_NO_STATUS;
352 return 0;
353 }
354
355 mcd_Play.start = qInfo.diskTime;
356
357 audioStatus = CDROM_AUDIO_PAUSED;
358 return 0;
359
360 case CDROMRESUME:
361 if (audioStatus != CDROM_AUDIO_PAUSED)
362 return -EINVAL;
363
364
365
366 i = mcdPlay(&mcd_Play);
367 if (i < 0)
368 {
369 audioStatus = CDROM_AUDIO_ERROR;
370 return -EIO;
371 }
372
373 audioStatus = CDROM_AUDIO_PLAY;
374 return 0;
375
376 case CDROMPLAYTRKIND:
377
378 st = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
379 if (st)
380 return st;
381
382 memcpy_fromfs(&ti, (void *) arg, sizeof ti);
383
384 if (ti.cdti_trk0 < DiskInfo.first
385 || ti.cdti_trk0 > DiskInfo.last
386 || ti.cdti_trk1 < ti.cdti_trk0)
387 {
388 return -EINVAL;
389 }
390
391 if (ti.cdti_trk1 > DiskInfo.last)
392 ti. cdti_trk1 = DiskInfo.last;
393
394 mcd_Play.start = Toc[ti.cdti_trk0].diskTime;
395 mcd_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
396
397 #ifdef MCD_DEBUG
398 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
399 mcd_Play.start.min, mcd_Play.start.sec, mcd_Play.start.frame,
400 mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame);
401 #endif
402
403 i = mcdPlay(&mcd_Play);
404 if (i < 0)
405 {
406 audioStatus = CDROM_AUDIO_ERROR;
407 return -EIO;
408 }
409
410 audioStatus = CDROM_AUDIO_PLAY;
411 return 0;
412
413 case CDROMPLAYMSF:
414
415 if (audioStatus == CDROM_AUDIO_PLAY) {
416 outb(MCMD_STOP, MCDPORT(0));
417 i = getMcdStatus(MCD_STATUS_DELAY);
418 audioStatus = CDROM_AUDIO_NO_STATUS;
419 }
420
421 st = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
422 if (st)
423 return st;
424
425 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
426
427
428
429 bin2bcd(&msf.cdmsf_min0);
430 bin2bcd(&msf.cdmsf_sec0);
431 bin2bcd(&msf.cdmsf_frame0);
432 bin2bcd(&msf.cdmsf_min1);
433 bin2bcd(&msf.cdmsf_sec1);
434 bin2bcd(&msf.cdmsf_frame1);
435
436 mcd_Play.start.min = msf.cdmsf_min0;
437 mcd_Play.start.sec = msf.cdmsf_sec0;
438 mcd_Play.start.frame = msf.cdmsf_frame0;
439 mcd_Play.end.min = msf.cdmsf_min1;
440 mcd_Play.end.sec = msf.cdmsf_sec1;
441 mcd_Play.end.frame = msf.cdmsf_frame1;
442
443 #ifdef MCD_DEBUG
444 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
445 mcd_Play.start.min, mcd_Play.start.sec, mcd_Play.start.frame,
446 mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame);
447 #endif
448
449 i = mcdPlay(&mcd_Play);
450 if (i < 0)
451 {
452 audioStatus = CDROM_AUDIO_ERROR;
453 return -EIO;
454 }
455
456 audioStatus = CDROM_AUDIO_PLAY;
457 return 0;
458
459 case CDROMREADTOCHDR:
460 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof tocHdr);
461 if (st)
462 return st;
463
464 tocHdr.cdth_trk0 = DiskInfo.first;
465 tocHdr.cdth_trk1 = DiskInfo.last;
466 memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr);
467 return 0;
468
469 case CDROMREADTOCENTRY:
470
471 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
472 if (st)
473 return st;
474
475 memcpy_fromfs(&entry, (void *) arg, sizeof entry);
476 if (entry.cdte_track == CDROM_LEADOUT)
477
478 tocPtr = &Toc[DiskInfo.last + 1];
479
480 else if (entry.cdte_track > DiskInfo.last
481 || entry.cdte_track < DiskInfo.first)
482 return -EINVAL;
483
484 else
485 tocPtr = &Toc[entry.cdte_track];
486
487 entry.cdte_adr = tocPtr -> ctrl_addr;
488 entry.cdte_ctrl = tocPtr -> ctrl_addr >> 4;
489
490 if (entry.cdte_format == CDROM_LBA)
491 entry.cdte_addr.lba = msf2hsg(&tocPtr -> diskTime);
492
493 else if (entry.cdte_format == CDROM_MSF)
494 {
495 entry.cdte_addr.msf.minute = bcd2bin(tocPtr -> diskTime.min);
496 entry.cdte_addr.msf.second = bcd2bin(tocPtr -> diskTime.sec);
497 entry.cdte_addr.msf.frame = bcd2bin(tocPtr -> diskTime.frame);
498 }
499
500 else
501 return -EINVAL;
502
503 memcpy_tofs((void *) arg, &entry, sizeof entry);
504 return 0;
505
506 case CDROMSUBCHNL:
507
508 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof subchnl);
509 if (st)
510 return st;
511
512 memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
513
514 if (GetQChannelInfo(&qInfo) < 0)
515 return -EIO;
516
517 subchnl.cdsc_audiostatus = audioStatus;
518 subchnl.cdsc_adr = qInfo.ctrl_addr;
519 subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
520 subchnl.cdsc_trk = bcd2bin(qInfo.track);
521 subchnl.cdsc_ind = bcd2bin(qInfo.pointIndex);
522
523 if (subchnl.cdsc_format == CDROM_LBA)
524 {
525 subchnl.cdsc_absaddr.lba = msf2hsg(&qInfo.diskTime);
526 subchnl.cdsc_reladdr.lba = msf2hsg(&qInfo.trackTime);
527 }
528
529 else if (subchnl.cdsc_format == CDROM_MSF)
530 {
531 subchnl.cdsc_absaddr.msf.minute = bcd2bin(qInfo.diskTime.min);
532 subchnl.cdsc_absaddr.msf.second = bcd2bin(qInfo.diskTime.sec);
533 subchnl.cdsc_absaddr.msf.frame = bcd2bin(qInfo.diskTime.frame);
534
535 subchnl.cdsc_reladdr.msf.minute = bcd2bin(qInfo.trackTime.min);
536 subchnl.cdsc_reladdr.msf.second = bcd2bin(qInfo.trackTime.sec);
537 subchnl.cdsc_reladdr.msf.frame = bcd2bin(qInfo.trackTime.frame);
538 }
539
540 else
541 return -EINVAL;
542
543 memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
544 return 0;
545
546 case CDROMVOLCTRL:
547 st = verify_area(VERIFY_READ, (void *) arg, sizeof(volctrl));
548 if (st)
549 return st;
550
551 memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
552 outb(MCMD_SET_VOLUME, MCDPORT(0));
553 outb(volctrl.channel0, MCDPORT(0));
554 outb(255, MCDPORT(0));
555 outb(volctrl.channel1, MCDPORT(0));
556 outb(255, MCDPORT(0));
557
558 i = getMcdStatus(MCD_STATUS_DELAY);
559 if (i < 0)
560 return -EIO;
561
562 {
563 char a, b, c, d;
564
565 getValue(&a);
566 getValue(&b);
567 getValue(&c);
568 getValue(&d);
569 }
570
571 return 0;
572
573 case CDROMEJECT:
574
575 if (audioStatus == CDROM_AUDIO_PLAY) {
576 outb(MCMD_STOP, MCDPORT(0));
577 i = getMcdStatus(MCD_STATUS_DELAY);
578 }
579
580 audioStatus = CDROM_AUDIO_NO_STATUS;
581
582 outb(MCMD_EJECT, MCDPORT(0));
583
584
585
586
587
588 i = getMcdStatus(MCD_STATUS_DELAY);
589 return 0;
590 default:
591 return -EINVAL;
592 }
593 }
594
595
596
597
598
599
600
601 static void
602 mcd_transfer(void)
603 {
604 if (CURRENT_VALID) {
605 while (CURRENT -> nr_sectors) {
606 int bn = CURRENT -> sector / 4;
607 int i;
608 for (i = 0; i < MCD_BUF_SIZ && mcd_buf_bn[i] != bn; ++i)
609 ;
610 if (i < MCD_BUF_SIZ) {
611 int offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
612 int nr_sectors = 4 - (CURRENT -> sector & 3);
613 if (mcd_buf_out != i) {
614 mcd_buf_out = i;
615 if (mcd_buf_bn[i] != bn) {
616 mcd_buf_out = -1;
617 continue;
618 }
619 }
620 if (nr_sectors > CURRENT -> nr_sectors)
621 nr_sectors = CURRENT -> nr_sectors;
622 memcpy(CURRENT -> buffer, mcd_buf + offs, nr_sectors * 512);
623 CURRENT -> nr_sectors -= nr_sectors;
624 CURRENT -> sector += nr_sectors;
625 CURRENT -> buffer += nr_sectors * 512;
626 } else {
627 mcd_buf_out = -1;
628 break;
629 }
630 }
631 }
632 }
633
634
635
636
637
638
639
640 static void
641 mcd_interrupt(int irq, struct pt_regs * regs)
642 {
643 int st;
644
645 st = inb(MCDPORT(1)) & 0xFF;
646 #ifdef TEST1
647 printk("<int1-%02X>", st);
648 #endif
649 if (!(st & MFL_STATUS))
650 {
651 st = inb(MCDPORT(0)) & 0xFF;
652 #ifdef TEST1
653 printk("<int0-%02X>", st);
654 #endif
655 if ((st & 0xFF) != 0xFF)
656 mcd_error = st ? st & 0xFF : -1;
657 }
658 }
659
660
661 static void
662 do_mcd_request(void)
663 {
664 #ifdef TEST2
665 printk(" do_mcd_request(%ld+%ld)\n", CURRENT -> sector, CURRENT -> nr_sectors);
666 #endif
667 mcd_transfer_is_active = 1;
668 while (CURRENT_VALID) {
669 if (CURRENT->bh) {
670 if (!CURRENT->bh->b_lock)
671 panic(DEVICE_NAME ": block not locked");
672 }
673 mcd_transfer();
674 if (CURRENT -> nr_sectors == 0) {
675 end_request(1);
676 } else {
677 mcd_buf_out = -1;
678 if (mcd_state == MCD_S_IDLE) {
679 if (!tocUpToDate) {
680 if (updateToc() < 0) {
681 while (CURRENT_VALID)
682 end_request(0);
683 break;
684 }
685 }
686 mcd_state = MCD_S_START;
687 McdTries = 5;
688 SET_TIMER(mcd_poll, 1);
689 }
690 break;
691 }
692 }
693 mcd_transfer_is_active = 0;
694 #ifdef TEST2
695 printk(" do_mcd_request ends\n");
696 #endif
697 }
698
699
700
701 static void
702 mcd_poll(void)
703 {
704 int st;
705
706
707 if (mcd_error)
708 {
709 if (mcd_error & 0xA5)
710 {
711 printk("mcd: I/O error 0x%02x", mcd_error);
712 if (mcd_error & 0x80)
713 printk(" (Door open)");
714 if (mcd_error & 0x20)
715 printk(" (Disk changed)");
716 if (mcd_error & 0x04)
717 {
718 printk(" (Read error)");
719
720
721
722
723
724
725
726
727 if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS && MCMD_DATA_READ == MCMD_2X_READ)
728 {
729 MCMD_DATA_READ = MCMD_PLAY_READ;
730 mcd1xhold = SINGLE_HOLD_SECTORS;
731 printk(" Speed now 1x");
732 }
733 }
734 printk("\n");
735 mcd_invalidate_buffers();
736 #ifdef WARN_IF_READ_FAILURE
737 if (McdTries == MCD_RETRY_ATTEMPTS)
738 printk("mcd: read of block %d failed\n", mcd_next_bn);
739 #endif
740 if (!McdTries--)
741 {
742
743
744 printk("mcd: read of block %d failed, giving up\n", mcd_next_bn);
745 if (mcd_transfer_is_active)
746 {
747 McdTries = 0;
748 goto ret;
749 }
750 if (CURRENT_VALID)
751 end_request(0);
752 McdTries = MCD_RETRY_ATTEMPTS;
753 }
754 }
755 mcd_error = 0;
756 mcd_state = MCD_S_STOP;
757 }
758
759
760
761 if (mcdDouble == 1 && McdTries == MCD_RETRY_ATTEMPTS && MCMD_DATA_READ == MCMD_PLAY_READ)
762 {
763
764 if (mcd1xhold == 0)
765 {
766 MCMD_DATA_READ = MCMD_2X_READ;
767 printk("mcd: Switching back to 2X speed!\n");
768 }
769 else mcd1xhold--;
770
771 }
772
773
774
775 immediately:
776 switch (mcd_state) {
777
778
779
780 case MCD_S_IDLE:
781 #ifdef TEST3
782 printk("MCD_S_IDLE\n");
783 #endif
784 return;
785
786
787
788 case MCD_S_START:
789 #ifdef TEST3
790 printk("MCD_S_START\n");
791 #endif
792
793 outb(MCMD_GET_STATUS, MCDPORT(0));
794 mcd_state = mcd_mode == 1 ? MCD_S_READ : MCD_S_MODE;
795 McdTimeout = 3000;
796 break;
797
798
799
800 case MCD_S_MODE:
801 #ifdef TEST3
802 printk("MCD_S_MODE\n");
803 #endif
804
805 if ((st = mcdStatus()) != -1) {
806
807 if (st & MST_DSK_CHG) {
808 mcdDiskChanged = 1;
809 tocUpToDate = 0;
810 mcd_invalidate_buffers();
811 }
812
813 set_mode_immediately:
814
815 if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {
816 mcdDiskChanged = 1;
817 tocUpToDate = 0;
818 if (mcd_transfer_is_active) {
819 mcd_state = MCD_S_START;
820 goto immediately;
821 }
822 printk((st & MST_DOOR_OPEN) ? "mcd: door open\n" : "mcd: disk removed\n");
823 mcd_state = MCD_S_IDLE;
824 while (CURRENT_VALID)
825 end_request(0);
826 return;
827 }
828
829 outb(MCMD_SET_MODE, MCDPORT(0));
830 outb(1, MCDPORT(0));
831 mcd_mode = 1;
832 mcd_state = MCD_S_READ;
833 McdTimeout = 3000;
834
835 }
836 break;
837
838
839
840 case MCD_S_READ:
841 #ifdef TEST3
842 printk("MCD_S_READ\n");
843 #endif
844
845 if ((st = mcdStatus()) != -1) {
846
847 if (st & MST_DSK_CHG) {
848 mcdDiskChanged = 1;
849 tocUpToDate = 0;
850 mcd_invalidate_buffers();
851 }
852
853 read_immediately:
854
855 if ((st & MST_DOOR_OPEN) || !(st & MST_READY)) {
856 mcdDiskChanged = 1;
857 tocUpToDate = 0;
858 if (mcd_transfer_is_active) {
859 mcd_state = MCD_S_START;
860 goto immediately;
861 }
862 printk((st & MST_DOOR_OPEN) ? "mcd: door open\n" : "mcd: disk removed\n");
863 mcd_state = MCD_S_IDLE;
864 while (CURRENT_VALID)
865 end_request(0);
866 return;
867 }
868
869 if (CURRENT_VALID) {
870 struct mcd_Play_msf msf;
871 mcd_next_bn = CURRENT -> sector / 4;
872 hsg2msf(mcd_next_bn, &msf.start);
873 msf.end.min = ~0;
874 msf.end.sec = ~0;
875 msf.end.frame = ~0;
876 sendMcdCmd(MCMD_DATA_READ, &msf);
877 mcd_state = MCD_S_DATA;
878 McdTimeout = READ_TIMEOUT;
879 } else {
880 mcd_state = MCD_S_STOP;
881 goto immediately;
882 }
883
884 }
885 break;
886
887
888 case MCD_S_DATA:
889 #ifdef TEST3
890 printk("MCD_S_DATA\n");
891 #endif
892
893 st = inb(MCDPORT(1)) & (MFL_STATUSorDATA);
894 data_immediately:
895 #ifdef TEST5
896 printk("Status %02x\n",st);
897 #endif
898 switch (st) {
899
900 case MFL_DATA:
901 #ifdef WARN_IF_READ_FAILURE
902 if (McdTries == 5)
903 printk("mcd: read of block %d failed\n", mcd_next_bn);
904 #endif
905 if (!McdTries--) {
906 printk("mcd: read of block %d failed, giving up\n", mcd_next_bn);
907 if (mcd_transfer_is_active) {
908 McdTries = 0;
909 break;
910 }
911 if (CURRENT_VALID)
912 end_request(0);
913 McdTries = 5;
914 }
915 mcd_state = MCD_S_START;
916 McdTimeout = READ_TIMEOUT;
917 goto immediately;
918
919 case MFL_STATUSorDATA:
920 break;
921
922 default:
923 McdTries = 5;
924 if (!CURRENT_VALID && mcd_buf_in == mcd_buf_out) {
925 mcd_state = MCD_S_STOP;
926 goto immediately;
927 }
928 mcd_buf_bn[mcd_buf_in] = -1;
929 READ_DATA(MCDPORT(0), mcd_buf + 2048 * mcd_buf_in, 2048);
930 mcd_buf_bn[mcd_buf_in] = mcd_next_bn++;
931 if (mcd_buf_out == -1)
932 mcd_buf_out = mcd_buf_in;
933 mcd_buf_in = mcd_buf_in + 1 == MCD_BUF_SIZ ? 0 : mcd_buf_in + 1;
934 if (!mcd_transfer_is_active) {
935 while (CURRENT_VALID) {
936 mcd_transfer();
937 if (CURRENT -> nr_sectors == 0)
938 end_request(1);
939 else
940 break;
941 }
942 }
943
944 if (CURRENT_VALID
945 && (CURRENT -> sector / 4 < mcd_next_bn ||
946 CURRENT -> sector / 4 > mcd_next_bn + 16)) {
947 mcd_state = MCD_S_STOP;
948 goto immediately;
949 }
950 McdTimeout = READ_TIMEOUT;
951 #ifdef DOUBLE_QUICK_ONLY
952 if (MCMD_DATA_READ != MCMD_PLAY_READ)
953 #endif
954 {
955 int count= QUICK_LOOP_COUNT;
956 while (count--) {
957 QUICK_LOOP_DELAY;
958 if ((st = (inb(MCDPORT(1))) & (MFL_STATUSorDATA)) != (MFL_STATUSorDATA)) {
959 # ifdef TEST4
960
961 printk(" %d ",QUICK_LOOP_COUNT-count);
962 # endif
963 goto data_immediately;
964 }
965 }
966 # ifdef TEST4
967
968 printk("ended ");
969 # endif
970 }
971 break;
972 }
973 break;
974
975
976
977 case MCD_S_STOP:
978 #ifdef TEST3
979 printk("MCD_S_STOP\n");
980 #endif
981
982 #ifdef WORK_AROUND_MITSUMI_BUG_93
983 if (!mitsumi_bug_93_wait)
984 goto do_not_work_around_mitsumi_bug_93_1;
985
986 McdTimeout = mitsumi_bug_93_wait;
987 mcd_state = 9+3+1;
988 break;
989
990 case 9+3+1:
991 if (McdTimeout)
992 break;
993
994 do_not_work_around_mitsumi_bug_93_1:
995 #endif
996
997 outb(MCMD_STOP, MCDPORT(0));
998
999 #ifdef WORK_AROUND_MITSUMI_BUG_92
1000 if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {
1001 int i = 4096;
1002 do {
1003 inb(MCDPORT(0));
1004 } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);
1005 outb(MCMD_STOP, MCDPORT(0));
1006 if ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS) {
1007 i = 4096;
1008 do {
1009 inb(MCDPORT(0));
1010 } while ((inb(MCDPORT(1)) & MFL_STATUSorDATA) == MFL_STATUS && --i);
1011 outb(MCMD_STOP, MCDPORT(0));
1012 }
1013 }
1014 #endif
1015
1016 mcd_state = MCD_S_STOPPING;
1017 McdTimeout = 1000;
1018 break;
1019
1020 case MCD_S_STOPPING:
1021 #ifdef TEST3
1022 printk("MCD_S_STOPPING\n");
1023 #endif
1024
1025 if ((st = mcdStatus()) == -1 && McdTimeout)
1026 break;
1027
1028 if ((st != -1) && (st & MST_DSK_CHG)) {
1029 mcdDiskChanged = 1;
1030 tocUpToDate = 0;
1031 mcd_invalidate_buffers();
1032 }
1033
1034 #ifdef WORK_AROUND_MITSUMI_BUG_93
1035 if (!mitsumi_bug_93_wait)
1036 goto do_not_work_around_mitsumi_bug_93_2;
1037
1038 McdTimeout = mitsumi_bug_93_wait;
1039 mcd_state = 9+3+2;
1040 break;
1041
1042 case 9+3+2:
1043 if (McdTimeout)
1044 break;
1045
1046 st = -1;
1047
1048 do_not_work_around_mitsumi_bug_93_2:
1049 #endif
1050
1051 #ifdef TEST3
1052 printk("CURRENT_VALID %d mcd_mode %d\n",
1053 CURRENT_VALID, mcd_mode);
1054 #endif
1055
1056 if (CURRENT_VALID) {
1057 if (st != -1) {
1058 if (mcd_mode == 1)
1059 goto read_immediately;
1060 else
1061 goto set_mode_immediately;
1062 } else {
1063 mcd_state = MCD_S_START;
1064 McdTimeout = 1;
1065 }
1066 } else {
1067 mcd_state = MCD_S_IDLE;
1068 return;
1069 }
1070 break;
1071
1072 default:
1073 printk("mcd: invalid state %d\n", mcd_state);
1074 return;
1075 }
1076
1077 ret:
1078 if (!McdTimeout--) {
1079 printk("mcd: timeout in state %d\n", mcd_state);
1080 mcd_state = MCD_S_STOP;
1081 }
1082
1083 SET_TIMER(mcd_poll, 1);
1084 }
1085
1086
1087
1088 static void
1089 mcd_invalidate_buffers(void)
1090 {
1091 int i;
1092 for (i = 0; i < MCD_BUF_SIZ; ++i)
1093 mcd_buf_bn[i] = -1;
1094 mcd_buf_out = -1;
1095 }
1096
1097
1098
1099
1100
1101
1102 int
1103 mcd_open(struct inode *ip, struct file *fp)
1104 {
1105 int st;
1106
1107 if (mcdPresent == 0)
1108 return -ENXIO;
1109
1110 if (fp->f_mode & 2)
1111 return -EROFS;
1112
1113 if (!mcd_open_count && mcd_state == MCD_S_IDLE) {
1114
1115 mcd_invalidate_buffers();
1116
1117 st = statusCmd();
1118 if (st == -1)
1119 return -EIO;
1120
1121 if ((st & MST_READY) == 0)
1122 {
1123 printk("mcd: no disk in drive\n");
1124 return -EIO;
1125 }
1126
1127 if (updateToc() < 0)
1128 return -EIO;
1129
1130 }
1131 ++mcd_open_count;
1132 MOD_INC_USE_COUNT;
1133 return 0;
1134 }
1135
1136
1137
1138
1139
1140
1141 static void
1142 mcd_release(struct inode * inode, struct file * file)
1143 { MOD_DEC_USE_COUNT;
1144 if (!--mcd_open_count) {
1145 mcd_invalidate_buffers();
1146 sync_dev(inode->i_rdev);
1147 invalidate_buffers(inode -> i_rdev);
1148 }
1149 }
1150
1151
1152 static struct file_operations mcd_fops = {
1153 NULL,
1154 block_read,
1155 block_write,
1156 NULL,
1157 NULL,
1158 mcd_ioctl,
1159 NULL,
1160 mcd_open,
1161 mcd_release,
1162 NULL,
1163 NULL,
1164 check_mcd_change,
1165 NULL
1166 };
1167
1168
1169
1170
1171
1172
1173 int
1174 mcd_init(void)
1175 {
1176 int count;
1177 unsigned char result[3];
1178
1179 if (mcd_port <= 0 || mcd_irq <= 0) {
1180 printk("skip mcd_init\n");
1181 return -EIO;
1182 }
1183
1184 printk("mcd=0x%x,%d: ", mcd_port, mcd_irq);
1185
1186 if (register_blkdev(MAJOR_NR, "mcd", &mcd_fops) != 0)
1187 {
1188 printk("Unable to get major %d for Mitsumi CD-ROM\n",
1189 MAJOR_NR);
1190 return -EIO;
1191 }
1192
1193 if (check_region(mcd_port, 4)) {
1194 printk("Init failed, I/O port (%X) already in use\n",
1195 mcd_port);
1196 return -EIO;
1197 }
1198
1199 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1200 read_ahead[MAJOR_NR] = 4;
1201
1202
1203
1204 outb(0, MCDPORT(1));
1205 for (count = 0; count < 2000000; count++)
1206 (void) inb(MCDPORT(1));
1207
1208 outb(0x40, MCDPORT(0));
1209 for (count = 0; count < 2000000; count++)
1210 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1211 break;
1212
1213 if (count >= 2000000) {
1214 printk("Init failed. No mcd device at 0x%x irq %d\n",
1215 mcd_port, mcd_irq);
1216 return -EIO;
1217 }
1218 count = inb(MCDPORT(0));
1219
1220 outb(MCMD_GET_VERSION,MCDPORT(0));
1221 for(count=0;count<3;count++)
1222 if(getValue(result+count)) {
1223 printk("mitsumi get version failed at 0x%d\n",
1224 mcd_port);
1225 return -EIO;
1226 }
1227
1228 if (result[0] == result[1] && result[1] == result[2])
1229 return -EIO;
1230 printk("Mitsumi status, type and version : %02X %c %x ",
1231 result[0],result[1],result[2]);
1232
1233 if (result[1] == 'D')
1234 {
1235 printk("Double Speed CD ROM\n");
1236 MCMD_DATA_READ = MCMD_2X_READ;
1237 mcdDouble = 1;
1238 }
1239 else printk("Single Speed CD ROM\n");
1240
1241 mcdVersion=result[2];
1242
1243 if (mcdVersion >=4)
1244 outb(4,MCDPORT(2));
1245
1246
1247
1248 if (request_irq(mcd_irq, mcd_interrupt, SA_INTERRUPT, "Mitsumi CD"))
1249 {
1250 printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
1251 return -EIO;
1252 }
1253 request_region(mcd_port, 4,"mcd");
1254
1255 outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
1256 outb(0x02,MCDPORT(0));
1257 outb(0x00,MCDPORT(0));
1258 getValue(result);
1259
1260 outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
1261 outb(0x10,MCDPORT(0));
1262 outb(0x04,MCDPORT(0));
1263 getValue(result);
1264
1265 mcd_invalidate_buffers();
1266 mcdPresent = 1;
1267 return 0;
1268 }
1269
1270
1271 static void
1272 hsg2msf(long hsg, struct msf *msf)
1273 {
1274 hsg += 150;
1275 msf -> min = hsg / 4500;
1276 hsg %= 4500;
1277 msf -> sec = hsg / 75;
1278 msf -> frame = hsg % 75;
1279
1280 bin2bcd(&msf -> min);
1281 bin2bcd(&msf -> sec);
1282 bin2bcd(&msf -> frame);
1283 }
1284
1285
1286 static void
1287 bin2bcd(unsigned char *p)
1288 {
1289 int u, t;
1290
1291 u = *p % 10;
1292 t = *p / 10;
1293 *p = u | (t << 4);
1294 }
1295
1296 static int
1297 bcd2bin(unsigned char bcd)
1298 {
1299 return (bcd >> 4) * 10 + (bcd & 0xF);
1300 }
1301
1302
1303
1304
1305
1306
1307
1308 static int
1309 mcdStatus(void)
1310 {
1311 int i;
1312 int st;
1313
1314 st = inb(MCDPORT(1)) & MFL_STATUS;
1315 if (!st)
1316 {
1317 i = inb(MCDPORT(0)) & 0xFF;
1318 return i;
1319 }
1320 else
1321 return -1;
1322 }
1323
1324
1325
1326
1327
1328
1329 static void
1330 sendMcdCmd(int cmd, struct mcd_Play_msf *params)
1331 {
1332 outb(cmd, MCDPORT(0));
1333 outb(params -> start.min, MCDPORT(0));
1334 outb(params -> start.sec, MCDPORT(0));
1335 outb(params -> start.frame, MCDPORT(0));
1336 outb(params -> end.min, MCDPORT(0));
1337 outb(params -> end.sec, MCDPORT(0));
1338 outb(params -> end.frame, MCDPORT(0));
1339 }
1340
1341
1342
1343
1344
1345
1346
1347 static void
1348 mcdStatTimer(void)
1349 {
1350 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1351 {
1352 wake_up(&mcd_waitq);
1353 return;
1354 }
1355
1356 McdTimeout--;
1357 if (McdTimeout <= 0)
1358 {
1359 wake_up(&mcd_waitq);
1360 return;
1361 }
1362
1363 SET_TIMER(mcdStatTimer, 1);
1364 }
1365
1366
1367
1368
1369
1370
1371
1372
1373 static int
1374 getMcdStatus(int timeout)
1375 {
1376 int st;
1377
1378 McdTimeout = timeout;
1379 SET_TIMER(mcdStatTimer, 1);
1380 sleep_on(&mcd_waitq);
1381 if (McdTimeout <= 0)
1382 return -1;
1383
1384 st = inb(MCDPORT(0)) & 0xFF;
1385 if (st == 0xFF)
1386 return -1;
1387
1388 if ((st & MST_BUSY) == 0 && audioStatus == CDROM_AUDIO_PLAY)
1389
1390 audioStatus = CDROM_AUDIO_COMPLETED;
1391
1392 if (st & MST_DSK_CHG)
1393 {
1394 mcdDiskChanged = 1;
1395 tocUpToDate = 0;
1396 audioStatus = CDROM_AUDIO_NO_STATUS;
1397 }
1398
1399 return st;
1400 }
1401
1402
1403
1404
1405
1406
1407
1408 static int
1409 getValue(unsigned char *result)
1410 {
1411 int count;
1412 int s;
1413
1414 for (count = 0; count < 2000; count++)
1415 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1416 break;
1417
1418 if (count >= 2000)
1419 {
1420 printk("mcd: getValue timeout\n");
1421 return -1;
1422 }
1423
1424 s = inb(MCDPORT(0)) & 0xFF;
1425 *result = (unsigned char) s;
1426 return 0;
1427 }
1428
1429
1430
1431
1432
1433
1434
1435 int
1436 GetQChannelInfo(struct mcd_Toc *qp)
1437 {
1438 unsigned char notUsed;
1439 int retry;
1440
1441 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1442 {
1443 outb(MCMD_GET_Q_CHANNEL, MCDPORT(0));
1444 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1445 break;
1446 }
1447
1448 if (retry >= MCD_RETRY_ATTEMPTS)
1449 return -1;
1450
1451 if (getValue(&qp -> ctrl_addr) < 0) return -1;
1452 if (getValue(&qp -> track) < 0) return -1;
1453 if (getValue(&qp -> pointIndex) < 0) return -1;
1454 if (getValue(&qp -> trackTime.min) < 0) return -1;
1455 if (getValue(&qp -> trackTime.sec) < 0) return -1;
1456 if (getValue(&qp -> trackTime.frame) < 0) return -1;
1457 if (getValue(¬Used) < 0) return -1;
1458 if (getValue(&qp -> diskTime.min) < 0) return -1;
1459 if (getValue(&qp -> diskTime.sec) < 0) return -1;
1460 if (getValue(&qp -> diskTime.frame) < 0) return -1;
1461
1462 return 0;
1463 }
1464
1465
1466
1467
1468
1469
1470 static int
1471 updateToc()
1472 {
1473 if (tocUpToDate)
1474 return 0;
1475
1476 if (GetDiskInfo() < 0)
1477 return -EIO;
1478
1479 if (GetToc() < 0)
1480 return -EIO;
1481
1482 tocUpToDate = 1;
1483 return 0;
1484 }
1485
1486
1487
1488
1489
1490
1491 static int
1492 GetDiskInfo()
1493 {
1494 int retry;
1495
1496 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1497 {
1498 outb(MCMD_GET_DISK_INFO, MCDPORT(0));
1499 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1500 break;
1501 }
1502
1503 if (retry >= MCD_RETRY_ATTEMPTS)
1504 return -1;
1505
1506 if (getValue(&DiskInfo.first) < 0) return -1;
1507 if (getValue(&DiskInfo.last) < 0) return -1;
1508
1509 DiskInfo.first = bcd2bin(DiskInfo.first);
1510 DiskInfo.last = bcd2bin(DiskInfo.last);
1511
1512 if (getValue(&DiskInfo.diskLength.min) < 0) return -1;
1513 if (getValue(&DiskInfo.diskLength.sec) < 0) return -1;
1514 if (getValue(&DiskInfo.diskLength.frame) < 0) return -1;
1515 if (getValue(&DiskInfo.firstTrack.min) < 0) return -1;
1516 if (getValue(&DiskInfo.firstTrack.sec) < 0) return -1;
1517 if (getValue(&DiskInfo.firstTrack.frame) < 0) return -1;
1518
1519 #ifdef MCD_DEBUG
1520 printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
1521 DiskInfo.first,
1522 DiskInfo.last,
1523 DiskInfo.diskLength.min,
1524 DiskInfo.diskLength.sec,
1525 DiskInfo.diskLength.frame,
1526 DiskInfo.firstTrack.min,
1527 DiskInfo.firstTrack.sec,
1528 DiskInfo.firstTrack.frame);
1529 #endif
1530
1531 return 0;
1532 }
1533
1534
1535
1536
1537
1538
1539 static int
1540 GetToc()
1541 {
1542 int i, px;
1543 int limit;
1544 int retry;
1545 struct mcd_Toc qInfo;
1546
1547 for (i = 0; i < MAX_TRACKS; i++)
1548 Toc[i].pointIndex = 0;
1549
1550 i = DiskInfo.last + 3;
1551
1552 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1553 {
1554 outb(MCMD_STOP, MCDPORT(0));
1555 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1556 break;
1557 }
1558
1559 if (retry >= MCD_RETRY_ATTEMPTS)
1560 return -1;
1561
1562 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1563 {
1564 outb(MCMD_SET_MODE, MCDPORT(0));
1565 outb(0x05, MCDPORT(0));
1566 mcd_mode = 0x05;
1567 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1568 break;
1569 }
1570
1571 if (retry >= MCD_RETRY_ATTEMPTS)
1572 return -1;
1573
1574 for (limit = 300; limit > 0; limit--)
1575 {
1576 if (GetQChannelInfo(&qInfo) < 0)
1577 break;
1578
1579 px = bcd2bin(qInfo.pointIndex);
1580 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
1581 if (Toc[px].pointIndex == 0)
1582 {
1583 Toc[px] = qInfo;
1584 i--;
1585 }
1586
1587 if (i <= 0)
1588 break;
1589 }
1590
1591 Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
1592
1593 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1594 {
1595 outb(MCMD_SET_MODE, MCDPORT(0));
1596 outb(0x01, MCDPORT(0));
1597 mcd_mode = 1;
1598 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1599 break;
1600 }
1601
1602 #ifdef MCD_DEBUG
1603 for (i = 1; i <= DiskInfo.last; i++)
1604 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1605 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1606 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1607 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1608 for (i = 100; i < 103; i++)
1609 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1610 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1611 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1612 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1613 #endif
1614
1615 return limit > 0 ? 0 : -1;
1616 }
1617
1618 #ifdef MODULE
1619 void cleanup_module(void)
1620 { if (MOD_IN_USE)
1621 { printk("mcd module in use - can't remove it.\n");
1622 return;
1623 }
1624 if ((unregister_blkdev(MAJOR_NR, "mcd") == -EINVAL))
1625 { printk("What's that: can't unregister mcd\n");
1626 return;
1627 }
1628 release_region(mcd_port,4);
1629 free_irq(mcd_irq);
1630 printk("mcd module released.\n");
1631 }
1632 #endif MODULE