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