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