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