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