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