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