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