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