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