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