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 immediatly:
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_immediatly:
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 immediatly;
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_immediatly:
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 immediatly;
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 immediatly;
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_immediatly:
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 immediatly;
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 immediatly;
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 immediatly;
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_immediatly;
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_immediatly;
983 else
984 goto set_mode_immediatly;
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 (!mcd_open_count && mcd_state == MCD_S_IDLE) {
1034
1035 mcd_invalidate_buffers();
1036
1037 st = statusCmd();
1038 if (st == -1)
1039 return -EIO;
1040
1041 if ((st & MST_READY) == 0)
1042 {
1043 printk("mcd: no disk in drive\n");
1044 return -EIO;
1045 }
1046
1047 if (updateToc() < 0)
1048 return -EIO;
1049
1050 }
1051 ++mcd_open_count;
1052
1053 return 0;
1054 }
1055
1056
1057
1058
1059
1060
1061 static void
1062 mcd_release(struct inode * inode, struct file * file)
1063 {
1064 if (!--mcd_open_count) {
1065 mcd_invalidate_buffers();
1066 sync_dev(inode->i_rdev);
1067 invalidate_buffers(inode -> i_rdev);
1068 }
1069 }
1070
1071
1072 static struct file_operations mcd_fops = {
1073 NULL,
1074 block_read,
1075 block_write,
1076 NULL,
1077 NULL,
1078 mcd_ioctl,
1079 NULL,
1080 mcd_open,
1081 mcd_release,
1082 NULL,
1083 NULL,
1084 check_mcd_change,
1085 NULL
1086 };
1087
1088
1089
1090
1091
1092
1093 static struct sigaction mcd_sigaction = {
1094 mcd_interrupt,
1095 0,
1096 SA_INTERRUPT,
1097 NULL
1098 };
1099
1100
1101
1102
1103
1104
1105 unsigned long
1106 mcd_init(unsigned long mem_start, unsigned long mem_end)
1107 {
1108 int count;
1109 unsigned char result[3];
1110
1111 if (mcd_port <= 0 || mcd_irq <= 0) {
1112 printk("skip mcd_init\n");
1113 return mem_start;
1114 }
1115
1116 printk("mcd=0x%x,%d: ", mcd_port, mcd_irq);
1117
1118 if (register_blkdev(MAJOR_NR, "mcd", &mcd_fops) != 0)
1119 {
1120 printk("Unable to get major %d for Mitsumi CD-ROM\n",
1121 MAJOR_NR);
1122 return mem_start;
1123 }
1124
1125 if (check_region(mcd_port, 4)) {
1126 printk("Init failed, I/O port (%X) already in use\n",
1127 mcd_port);
1128 return mem_start;
1129 }
1130
1131 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1132 read_ahead[MAJOR_NR] = 4;
1133
1134
1135
1136 outb(0, MCDPORT(1));
1137 for (count = 0; count < 2000000; count++)
1138 (void) inb(MCDPORT(1));
1139
1140 outb(0x40, MCDPORT(0));
1141 for (count = 0; count < 2000000; count++)
1142 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1143 break;
1144
1145 if (count >= 2000000) {
1146 printk("Init failed. No mcd device at 0x%x irq %d\n",
1147 mcd_port, mcd_irq);
1148 return mem_start;
1149 }
1150 count = inb(MCDPORT(0));
1151
1152 outb(MCMD_GET_VERSION,MCDPORT(0));
1153 for(count=0;count<3;count++)
1154 if(getValue(result+count)) {
1155 printk("mitsumi get version failed at 0x%d\n",
1156 mcd_port);
1157 return mem_start;
1158 }
1159
1160 if (result[0] == result[1] && result[1] == result[2])
1161 return mem_start;
1162
1163 printk("Mitsumi status, type and version : %02X %c %x\n",
1164 result[0],result[1],result[2]);
1165
1166 if (result[1] == 'D') MCMD_DATA_READ= 0xC1;
1167
1168 mcdVersion=result[2];
1169
1170 if (mcdVersion >=4)
1171 outb(4,MCDPORT(2));
1172
1173
1174
1175 if (irqaction(mcd_irq, &mcd_sigaction))
1176 {
1177 printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", mcd_irq);
1178 return mem_start;
1179 }
1180 snarf_region(mcd_port, 4);
1181
1182 outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
1183 outb(0x02,MCDPORT(0));
1184 outb(0x00,MCDPORT(0));
1185 getValue(result);
1186
1187 outb(MCMD_CONFIG_DRIVE, MCDPORT(0));
1188 outb(0x10,MCDPORT(0));
1189 outb(0x04,MCDPORT(0));
1190 getValue(result);
1191
1192 mcd_invalidate_buffers();
1193 mcdPresent = 1;
1194 printk("\n");
1195 return mem_start;
1196 }
1197
1198
1199 static void
1200 hsg2msf(long hsg, struct msf *msf)
1201 {
1202 hsg += 150;
1203 msf -> min = hsg / 4500;
1204 hsg %= 4500;
1205 msf -> sec = hsg / 75;
1206 msf -> frame = hsg % 75;
1207
1208 bin2bcd(&msf -> min);
1209 bin2bcd(&msf -> sec);
1210 bin2bcd(&msf -> frame);
1211 }
1212
1213
1214 static void
1215 bin2bcd(unsigned char *p)
1216 {
1217 int u, t;
1218
1219 u = *p % 10;
1220 t = *p / 10;
1221 *p = u | (t << 4);
1222 }
1223
1224 static int
1225 bcd2bin(unsigned char bcd)
1226 {
1227 return (bcd >> 4) * 10 + (bcd & 0xF);
1228 }
1229
1230
1231
1232
1233
1234
1235
1236 static int
1237 mcdStatus(void)
1238 {
1239 int i;
1240 int st;
1241
1242 st = inb(MCDPORT(1)) & MFL_STATUS;
1243 if (!st)
1244 {
1245 i = inb(MCDPORT(0)) & 0xFF;
1246 return i;
1247 }
1248 else
1249 return -1;
1250 }
1251
1252
1253
1254
1255
1256
1257 static void
1258 sendMcdCmd(int cmd, struct mcd_Play_msf *params)
1259 {
1260 outb(cmd, MCDPORT(0));
1261 outb(params -> start.min, MCDPORT(0));
1262 outb(params -> start.sec, MCDPORT(0));
1263 outb(params -> start.frame, MCDPORT(0));
1264 outb(params -> end.min, MCDPORT(0));
1265 outb(params -> end.sec, MCDPORT(0));
1266 outb(params -> end.frame, MCDPORT(0));
1267 }
1268
1269
1270
1271
1272
1273
1274
1275 static void
1276 mcdStatTimer(void)
1277 {
1278 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1279 {
1280 wake_up(&mcd_waitq);
1281 return;
1282 }
1283
1284 McdTimeout--;
1285 if (McdTimeout <= 0)
1286 {
1287 wake_up(&mcd_waitq);
1288 return;
1289 }
1290
1291 SET_TIMER(mcdStatTimer, 1);
1292 }
1293
1294
1295
1296
1297
1298
1299
1300
1301 static int
1302 getMcdStatus(int timeout)
1303 {
1304 int st;
1305
1306 McdTimeout = timeout;
1307 SET_TIMER(mcdStatTimer, 1);
1308 sleep_on(&mcd_waitq);
1309 if (McdTimeout <= 0)
1310 return -1;
1311
1312 st = inb(MCDPORT(0)) & 0xFF;
1313 if (st == 0xFF)
1314 return -1;
1315
1316 if ((st & MST_BUSY) == 0 && audioStatus == CDROM_AUDIO_PLAY)
1317
1318 audioStatus = CDROM_AUDIO_COMPLETED;
1319
1320 if (st & MST_DSK_CHG)
1321 {
1322 mcdDiskChanged = 1;
1323 tocUpToDate = 0;
1324 audioStatus = CDROM_AUDIO_NO_STATUS;
1325 }
1326
1327 return st;
1328 }
1329
1330
1331
1332
1333
1334
1335
1336 static int
1337 getValue(unsigned char *result)
1338 {
1339 int count;
1340 int s;
1341
1342 for (count = 0; count < 2000; count++)
1343 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1344 break;
1345
1346 if (count >= 2000)
1347 {
1348 printk("mcd: getValue timeout\n");
1349 return -1;
1350 }
1351
1352 s = inb(MCDPORT(0)) & 0xFF;
1353 *result = (unsigned char) s;
1354 return 0;
1355 }
1356
1357
1358
1359
1360
1361
1362
1363 int
1364 GetQChannelInfo(struct mcd_Toc *qp)
1365 {
1366 unsigned char notUsed;
1367 int retry;
1368
1369 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1370 {
1371 outb(MCMD_GET_Q_CHANNEL, MCDPORT(0));
1372 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1373 break;
1374 }
1375
1376 if (retry >= MCD_RETRY_ATTEMPTS)
1377 return -1;
1378
1379 if (getValue(&qp -> ctrl_addr) < 0) return -1;
1380 if (getValue(&qp -> track) < 0) return -1;
1381 if (getValue(&qp -> pointIndex) < 0) return -1;
1382 if (getValue(&qp -> trackTime.min) < 0) return -1;
1383 if (getValue(&qp -> trackTime.sec) < 0) return -1;
1384 if (getValue(&qp -> trackTime.frame) < 0) return -1;
1385 if (getValue(¬Used) < 0) return -1;
1386 if (getValue(&qp -> diskTime.min) < 0) return -1;
1387 if (getValue(&qp -> diskTime.sec) < 0) return -1;
1388 if (getValue(&qp -> diskTime.frame) < 0) return -1;
1389
1390 return 0;
1391 }
1392
1393
1394
1395
1396
1397
1398 static int
1399 updateToc()
1400 {
1401 if (tocUpToDate)
1402 return 0;
1403
1404 if (GetDiskInfo() < 0)
1405 return -EIO;
1406
1407 if (GetToc() < 0)
1408 return -EIO;
1409
1410 tocUpToDate = 1;
1411 return 0;
1412 }
1413
1414
1415
1416
1417
1418
1419 static int
1420 GetDiskInfo()
1421 {
1422 int retry;
1423
1424 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1425 {
1426 outb(MCMD_GET_DISK_INFO, MCDPORT(0));
1427 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1428 break;
1429 }
1430
1431 if (retry >= MCD_RETRY_ATTEMPTS)
1432 return -1;
1433
1434 if (getValue(&DiskInfo.first) < 0) return -1;
1435 if (getValue(&DiskInfo.last) < 0) return -1;
1436
1437 DiskInfo.first = bcd2bin(DiskInfo.first);
1438 DiskInfo.last = bcd2bin(DiskInfo.last);
1439
1440 if (getValue(&DiskInfo.diskLength.min) < 0) return -1;
1441 if (getValue(&DiskInfo.diskLength.sec) < 0) return -1;
1442 if (getValue(&DiskInfo.diskLength.frame) < 0) return -1;
1443 if (getValue(&DiskInfo.firstTrack.min) < 0) return -1;
1444 if (getValue(&DiskInfo.firstTrack.sec) < 0) return -1;
1445 if (getValue(&DiskInfo.firstTrack.frame) < 0) return -1;
1446
1447 #ifdef MCD_DEBUG
1448 printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
1449 DiskInfo.first,
1450 DiskInfo.last,
1451 DiskInfo.diskLength.min,
1452 DiskInfo.diskLength.sec,
1453 DiskInfo.diskLength.frame,
1454 DiskInfo.firstTrack.min,
1455 DiskInfo.firstTrack.sec,
1456 DiskInfo.firstTrack.frame);
1457 #endif
1458
1459 return 0;
1460 }
1461
1462
1463
1464
1465
1466
1467 static int
1468 GetToc()
1469 {
1470 int i, px;
1471 int limit;
1472 int retry;
1473 struct mcd_Toc qInfo;
1474
1475 for (i = 0; i < MAX_TRACKS; i++)
1476 Toc[i].pointIndex = 0;
1477
1478 i = DiskInfo.last + 3;
1479
1480 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1481 {
1482 outb(MCMD_STOP, MCDPORT(0));
1483 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1484 break;
1485 }
1486
1487 if (retry >= MCD_RETRY_ATTEMPTS)
1488 return -1;
1489
1490 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1491 {
1492 outb(MCMD_SET_MODE, MCDPORT(0));
1493 outb(0x05, MCDPORT(0));
1494 mcd_mode = 0x05;
1495 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1496 break;
1497 }
1498
1499 if (retry >= MCD_RETRY_ATTEMPTS)
1500 return -1;
1501
1502 for (limit = 300; limit > 0; limit--)
1503 {
1504 if (GetQChannelInfo(&qInfo) < 0)
1505 break;
1506
1507 px = bcd2bin(qInfo.pointIndex);
1508 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
1509 if (Toc[px].pointIndex == 0)
1510 {
1511 Toc[px] = qInfo;
1512 i--;
1513 }
1514
1515 if (i <= 0)
1516 break;
1517 }
1518
1519 Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
1520
1521 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1522 {
1523 outb(MCMD_SET_MODE, MCDPORT(0));
1524 outb(0x01, MCDPORT(0));
1525 mcd_mode = 1;
1526 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1527 break;
1528 }
1529
1530 #ifdef MCD_DEBUG
1531 for (i = 1; i <= DiskInfo.last; i++)
1532 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1533 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1534 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1535 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1536 for (i = 100; i < 103; i++)
1537 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1538 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1539 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1540 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1541 #endif
1542
1543 return limit > 0 ? 0 : -1;
1544 }
1545