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