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