This source file includes following definitions.
- check_mcd_media_change
- statusCmd
- mcdPlay
- msf2hsg
- mcd_ioctl
- mcd_transfer
- mcd_interrupt
- do_mcd_request
- mcd_start
- mcd_status
- mcd_read_cmd
- mcd_data
- 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 #include <linux/config.h>
34 #ifdef CONFIG_MCD
35
36 #include <linux/errno.h>
37 #include <linux/signal.h>
38 #include <linux/sched.h>
39 #include <linux/timer.h>
40 #include <linux/fs.h>
41 #include <linux/kernel.h>
42 #include <linux/cdrom.h>
43
44
45 #include <asm/system.h>
46 #include <asm/io.h>
47 #include <asm/segment.h>
48
49 #define MAJOR_NR 23
50 #include "blk.h"
51 #include <linux/mcd.h>
52
53 #if 0
54 static int mcd_sizes[] = { 0 };
55 #endif
56
57 static int mcdPresent = 0;
58
59 static char mcd_buf[2048];
60 static int mcd_bn = -1;
61
62 static int McdTimeout, McdTries;
63 static struct wait_queue *mcd_waitq = NULL;
64
65 static struct mcd_DiskInfo DiskInfo;
66 static struct mcd_Toc Toc[MAX_TRACKS];
67 static struct mcd_Play_msf mcd_Play;
68
69 static int audioStatus;
70 static char mcdDiskChanged;
71 static char tocUpToDate;
72 static char mcdVersion;
73
74 static void mcd_transfer(void);
75 static void mcd_start(void);
76 static void mcd_status(void);
77 static void mcd_read_cmd(void);
78 static void mcd_data(void);
79 static void do_mcd_request(void);
80 static void hsg2msf(long hsg, struct msf *msf);
81 static void bin2bcd(unsigned char *p);
82 static int bcd2bin(unsigned char bcd);
83 static int mcdStatus(void);
84 static void sendMcdCmd(int cmd, struct mcd_Play_msf *params);
85 static int getMcdStatus(int timeout);
86 static int GetQChannelInfo(struct mcd_Toc *qp);
87 static int updateToc(void);
88 static int GetDiskInfo(void);
89 static int GetToc(void);
90 static int getValue(unsigned char *result);
91
92
93 int
94 check_mcd_media_change(int full_dev, int flag)
95 {
96 int retval, target;
97
98
99 target = MINOR(full_dev);
100
101 if (target > 0) {
102 printk("Mitsumi CD-ROM request error: invalid device.\n");
103 return 0;
104 }
105
106 retval = mcdDiskChanged;
107 if (!flag)
108 {
109 mcdDiskChanged = 0;
110 }
111
112 return retval;
113 }
114
115
116
117
118
119
120
121 static int
122 statusCmd(void)
123 {
124 int st, retry;
125
126 for (retry = 0; retry < 3; retry++)
127 {
128 outb(MCMD_GET_STATUS, MCDPORT(0));
129 st = getMcdStatus(100);
130 if (st != -1)
131 break;
132 }
133
134 return st;
135 }
136
137
138
139
140
141
142 static int
143 mcdPlay(struct mcd_Play_msf *arg)
144 {
145 int retry, st;
146
147 for (retry = 0; retry < 3; retry++)
148 {
149 sendMcdCmd(MCMD_PLAY_READ, arg);
150 st = getMcdStatus(200);
151 if (st != -1)
152 break;
153 }
154
155 return st;
156 }
157
158
159 long
160 msf2hsg(struct msf *mp)
161 {
162 return bcd2bin(mp -> frame)
163 + bcd2bin(mp -> sec) * 75
164 + bcd2bin(mp -> min) * 4500
165 - 150;
166 }
167
168
169 static int
170 mcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
171 unsigned long arg)
172 {
173 int i, st;
174 struct mcd_Toc qInfo;
175 struct cdrom_ti ti;
176 struct cdrom_tochdr tocHdr;
177 struct cdrom_msf msf;
178 struct cdrom_tocentry entry;
179 struct mcd_Toc *tocPtr;
180 struct cdrom_subchnl subchnl;
181 #if 0
182 struct cdrom_volctrl volctrl;
183 #endif
184
185 if (!ip)
186 return -EINVAL;
187
188 st = statusCmd();
189 if (st < 0)
190 return -EIO;
191
192 if (!tocUpToDate)
193 {
194 i = updateToc();
195 if (i < 0)
196 return i;
197 }
198
199 switch (cmd)
200 {
201 case CDROMSTART:
202
203
204
205
206
207 return 0;
208
209 case CDROMSTOP:
210 outb(MCMD_STOP, MCDPORT(0));
211 i = getMcdStatus(100);
212
213
214
215 audioStatus = CDROM_AUDIO_NO_STATUS;
216 return 0;
217
218 case CDROMPAUSE:
219 if (audioStatus != CDROM_AUDIO_PLAY)
220 return -EINVAL;
221
222 outb(MCMD_STOP, MCDPORT(0));
223 i = getMcdStatus(100);
224
225 if (GetQChannelInfo(&qInfo) < 0)
226 {
227
228
229 audioStatus = CDROM_AUDIO_NO_STATUS;
230 return 0;
231 }
232
233 mcd_Play.start = qInfo.diskTime;
234
235 audioStatus = CDROM_AUDIO_PAUSED;
236 return 0;
237
238 case CDROMRESUME:
239 if (audioStatus != CDROM_AUDIO_PAUSED)
240 return -EINVAL;
241
242
243
244 i = mcdPlay(&mcd_Play);
245 if (i < 0)
246 {
247 audioStatus = CDROM_AUDIO_ERROR;
248 return -EIO;
249 }
250
251 audioStatus = CDROM_AUDIO_PLAY;
252 return 0;
253
254 case CDROMPLAYTRKIND:
255
256 st = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
257 if (st)
258 return st;
259
260 memcpy_fromfs(&ti, (void *) arg, sizeof ti);
261
262 if (ti.cdti_trk0 < DiskInfo.first
263 || ti.cdti_trk0 > DiskInfo.last
264 || ti.cdti_trk1 < ti.cdti_trk0)
265 {
266 return -EINVAL;
267 }
268
269 if (ti.cdti_trk1 > DiskInfo.last)
270 ti. cdti_trk1 = DiskInfo.last;
271
272 mcd_Play.start = Toc[ti.cdti_trk0].diskTime;
273 mcd_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
274
275 #ifdef MCD_DEBUG
276 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
277 mcd_Play.start.min, mcd_Play.start.sec, mcd_Play.start.frame,
278 mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame);
279 #endif
280
281 i = mcdPlay(&mcd_Play);
282 if (i < 0)
283 {
284 audioStatus = CDROM_AUDIO_ERROR;
285 return -EIO;
286 }
287
288 audioStatus = CDROM_AUDIO_PLAY;
289 return 0;
290
291 case CDROMPLAYMSF:
292
293 if (audioStatus == CDROM_AUDIO_PLAY) {
294 outb(MCMD_STOP, MCDPORT(0));
295 i = getMcdStatus(100);
296 audioStatus = CDROM_AUDIO_NO_STATUS;
297 }
298
299 st = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
300 if (st)
301 return st;
302
303 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
304
305
306
307 bin2bcd(&msf.cdmsf_min0);
308 bin2bcd(&msf.cdmsf_sec0);
309 bin2bcd(&msf.cdmsf_frame0);
310 bin2bcd(&msf.cdmsf_min1);
311 bin2bcd(&msf.cdmsf_sec1);
312 bin2bcd(&msf.cdmsf_frame1);
313
314 mcd_Play.start.min = msf.cdmsf_min0;
315 mcd_Play.start.sec = msf.cdmsf_sec0;
316 mcd_Play.start.frame = msf.cdmsf_frame0;
317 mcd_Play.end.min = msf.cdmsf_min1;
318 mcd_Play.end.sec = msf.cdmsf_sec1;
319 mcd_Play.end.frame = msf.cdmsf_frame1;
320
321 #ifdef MCD_DEBUG
322 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
323 mcd_Play.start.min, mcd_Play.start.sec, mcd_Play.start.frame,
324 mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame);
325 #endif
326
327 i = mcdPlay(&mcd_Play);
328 if (i < 0)
329 {
330 audioStatus = CDROM_AUDIO_ERROR;
331 return -EIO;
332 }
333
334 audioStatus = CDROM_AUDIO_PLAY;
335 return 0;
336
337 case CDROMREADTOCHDR:
338 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof tocHdr);
339 if (st)
340 return st;
341
342 tocHdr.cdth_trk0 = DiskInfo.first;
343 tocHdr.cdth_trk1 = DiskInfo.last;
344 memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr);
345 return 0;
346
347 case CDROMREADTOCENTRY:
348
349 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
350 if (st)
351 return st;
352
353 memcpy_fromfs(&entry, (void *) arg, sizeof entry);
354 if (entry.cdte_track == CDROM_LEADOUT)
355
356 tocPtr = &Toc[DiskInfo.last + 1];
357
358 else if (entry.cdte_track > DiskInfo.last
359 || entry.cdte_track < DiskInfo.first)
360 return -EINVAL;
361
362 else
363 tocPtr = &Toc[entry.cdte_track];
364
365 entry.cdte_adr = tocPtr -> ctrl_addr;
366 entry.cdte_ctrl = tocPtr -> ctrl_addr >> 4;
367
368 if (entry.cdte_format == CDROM_LBA)
369 entry.cdte_addr.lba = msf2hsg(&tocPtr -> diskTime);
370
371 else if (entry.cdte_format == CDROM_MSF)
372 {
373 entry.cdte_addr.msf.minute = bcd2bin(tocPtr -> diskTime.min);
374 entry.cdte_addr.msf.second = bcd2bin(tocPtr -> diskTime.sec);
375 entry.cdte_addr.msf.frame = bcd2bin(tocPtr -> diskTime.frame);
376 }
377
378 else
379 return -EINVAL;
380
381 memcpy_tofs((void *) arg, &entry, sizeof entry);
382 return 0;
383
384 case CDROMSUBCHNL:
385
386 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof subchnl);
387 if (st)
388 return st;
389
390 memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
391
392 if (GetQChannelInfo(&qInfo) < 0)
393 return -EIO;
394
395 subchnl.cdsc_audiostatus = audioStatus;
396 subchnl.cdsc_adr = qInfo.ctrl_addr;
397 subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
398 subchnl.cdsc_trk = bcd2bin(qInfo.track);
399 subchnl.cdsc_ind = bcd2bin(qInfo.pointIndex);
400
401 if (subchnl.cdsc_format == CDROM_LBA)
402 {
403 subchnl.cdsc_absaddr.lba = msf2hsg(&qInfo.diskTime);
404 subchnl.cdsc_reladdr.lba = msf2hsg(&qInfo.trackTime);
405 }
406
407 else if (subchnl.cdsc_format == CDROM_MSF)
408 {
409 subchnl.cdsc_absaddr.msf.minute = bcd2bin(qInfo.diskTime.min);
410 subchnl.cdsc_absaddr.msf.second = bcd2bin(qInfo.diskTime.sec);
411 subchnl.cdsc_absaddr.msf.frame = bcd2bin(qInfo.diskTime.frame);
412
413 subchnl.cdsc_reladdr.msf.minute = bcd2bin(qInfo.trackTime.min);
414 subchnl.cdsc_reladdr.msf.second = bcd2bin(qInfo.trackTime.sec);
415 subchnl.cdsc_reladdr.msf.frame = bcd2bin(qInfo.trackTime.frame);
416 }
417
418 else
419 return -EINVAL;
420
421 memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
422 return 0;
423
424 case CDROMVOLCTRL:
425
426
427
428
429
430 #if 0
431 st = verify_area(VERIFY_READ, (void *) arg, sizeof(volctrl));
432 if (st)
433 return st;
434
435 memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
436 printk("VOL %d %d\n", volctrl.channel0 & 0xFF, volctrl.channel1 & 0xFF);
437 outb(MCMD_SET_VOLUME, MCDPORT(0));
438 outb(volctrl.channel0, MCDPORT(0));
439 outb(0, MCDPORT(0));
440 outb(volctrl.channel1, MCDPORT(0));
441 outb(1, MCDPORT(0));
442
443 i = getMcdStatus(100);
444 if (i < 0)
445 return -EIO;
446
447 {
448 int a, b, c, d;
449
450 getValue(&a);
451 getValue(&b);
452 getValue(&c);
453 getValue(&d);
454 printk("%02X %02X %02X %02X\n", a, b, c, d);
455 }
456
457 outb(0xF8, MCDPORT(0));
458 i = getMcdStatus(100);
459 printk("F8 -> %02X\n", i & 0xFF);
460 #endif
461 return 0;
462
463 case CDROMEJECT:
464 return 0;
465
466 default:
467 return -EINVAL;
468 }
469 }
470
471
472
473
474
475
476
477 static void
478 mcd_transfer(void)
479 {
480 long offs;
481
482 while (CURRENT -> nr_sectors > 0 && mcd_bn == CURRENT -> sector / 4)
483 {
484 offs = (CURRENT -> sector & 3) * 512;
485 memcpy(CURRENT -> buffer, mcd_buf + offs, 512);
486 CURRENT -> nr_sectors--;
487 CURRENT -> sector++;
488 CURRENT -> buffer += 512;
489 }
490 }
491
492
493
494
495
496
497
498 static void
499 mcd_interrupt(int unused)
500 {
501 int st;
502
503 st = inb(MCDPORT(1)) & 0xFF;
504 if (st != 0xFF)
505 {
506 st = inb(MCDPORT(0)) & 0xFF;
507 #if 0
508 printk("<int-%02X>", st);
509 #endif
510 }
511 }
512
513
514
515
516
517
518 static void
519 do_mcd_request(void)
520 {
521 unsigned int block,dev;
522 unsigned int nsect;
523
524 repeat:
525 INIT_REQUEST;
526 dev = MINOR(CURRENT->dev);
527 block = CURRENT->sector;
528 nsect = CURRENT->nr_sectors;
529
530 if (CURRENT == NULL || CURRENT -> sector == -1)
531 return;
532
533 if (CURRENT -> cmd != READ)
534 {
535 printk("mcd: bad cmd %d\n", CURRENT -> cmd);
536 end_request(0);
537 goto repeat;
538 }
539
540 mcd_transfer();
541
542
543
544 if (CURRENT -> nr_sectors == 0)
545 {
546 end_request(1);
547 goto repeat;
548 }
549
550 McdTries = 3;
551 mcd_start();
552 }
553
554
555
556
557
558
559 static void
560 mcd_start()
561 {
562 if (McdTries == 0)
563 {
564 printk("mcd: read failed after 3 tries\n");
565 end_request(0);
566 SET_TIMER(do_mcd_request, 1);
567 return;
568 }
569
570 McdTries--;
571 outb(0x40, MCDPORT(0));
572 McdTimeout = 100;
573 SET_TIMER(mcd_status, 1);
574 }
575
576
577
578
579
580
581
582 static void
583 mcd_status()
584 {
585 int st;
586
587 McdTimeout--;
588 st = mcdStatus();
589 if (st == -1)
590 {
591 if (McdTimeout == 0)
592 {
593 printk("mcd: status timed out\n");
594 SET_TIMER(mcd_start, 1);
595 return;
596 }
597
598 SET_TIMER(mcd_status, 1);
599 return;
600 }
601
602 if (st & MST_DSK_CHG)
603 {
604 mcdDiskChanged = 1;
605 }
606
607 if ((st & MST_READY) == 0)
608 {
609 printk("mcd: disk removed\n");
610 mcdDiskChanged = 1;
611 end_request(0);
612 do_mcd_request();
613 return;
614 }
615
616 outb(0x50, MCDPORT(0));
617 outb(0x01, MCDPORT(0));
618 McdTimeout = 100;
619 SET_TIMER(mcd_read_cmd, 1);
620 }
621
622
623
624
625
626
627
628 static void
629 mcd_read_cmd()
630 {
631 int st;
632 long block;
633 struct mcd_Play_msf mcdcmd;
634
635 McdTimeout--;
636 st = mcdStatus();
637
638 if (st & MST_DSK_CHG)
639 {
640 mcdDiskChanged = 1;
641 }
642
643 if (st == -1)
644 {
645 if (McdTimeout == 0)
646 {
647 printk("mcd: set mode timed out\n");
648 SET_TIMER(mcd_start, 1);
649 return;
650 }
651
652 SET_TIMER(mcd_read_cmd, 1);
653 return;
654 }
655
656 mcd_bn = -1;
657 block = CURRENT -> sector / 4;
658 hsg2msf(block, &mcdcmd.start);
659
660 mcdcmd.end.min = 0;
661 mcdcmd.end.sec = 0;
662 mcdcmd.end.frame = 1;
663
664 sendMcdCmd(MCMD_PLAY_READ, &mcdcmd);
665 McdTimeout = 200;
666 SET_TIMER(mcd_data, 1);
667 }
668
669
670
671
672
673
674
675 static void
676 mcd_data()
677 {
678 int i;
679
680 McdTimeout--;
681 cli();
682 i =inb(MCDPORT(1)) & (MFL_STATUS | MFL_DATA);
683 if (i == MFL_DATA)
684 {
685 printk("mcd: read failed\n");
686 #ifdef MCD_DEBUG
687 printk("got 0xB %02X\n", inb(MCDPORT(0)) & 0xFF);
688 #endif
689 SET_TIMER(mcd_start, 1);
690 sti();
691 return;
692 }
693
694 if (i == (MFL_STATUS | MFL_DATA))
695 {
696 if (McdTimeout == 0)
697 {
698 printk("mcd: data timeout, retrying\n");
699 SET_TIMER(mcd_start, 1);
700 }
701
702 else
703 SET_TIMER(mcd_data, 1);
704
705 sti();
706 return;
707 }
708
709 CLEAR_TIMER;
710 READ_DATA(MCDPORT(0), &mcd_buf[0], 2048);
711 sti();
712
713 mcd_bn = CURRENT -> sector / 4;
714 mcd_transfer();
715 end_request(1);
716 SET_TIMER(do_mcd_request, 1);
717 }
718
719
720
721
722
723
724 int
725 mcd_open(struct inode *ip, struct file *fp)
726 {
727 int st;
728
729 if (mcdPresent == 0)
730 return -ENXIO;
731
732 st = statusCmd();
733 if (st == -1)
734 return -EIO;
735
736 if ((st & MST_READY) == 0)
737 {
738 printk("mcd: no disk in drive\n");
739 return -EIO;
740 }
741
742 if (updateToc() < 0)
743 return -EIO;
744
745 return 0;
746 }
747
748
749
750
751
752
753 static void
754 mcd_release(struct inode * inode, struct file * file)
755 {
756 mcd_bn = -1;
757 sync_dev(inode->i_rdev);
758 invalidate_buffers(inode -> i_rdev);
759 }
760
761
762 static struct file_operations mcd_fops = {
763 NULL,
764 block_read,
765 block_write,
766 NULL,
767 NULL,
768 mcd_ioctl,
769 NULL,
770 mcd_open,
771 mcd_release
772 };
773
774
775
776
777
778
779 static struct sigaction mcd_sigaction = {
780 mcd_interrupt,
781 0,
782 SA_INTERRUPT,
783 NULL
784 };
785
786
787
788
789
790
791 unsigned long
792 mcd_init(unsigned long mem_start, unsigned long mem_end)
793 {
794 int count;
795 unsigned char result[3];
796
797 if (register_blkdev(MAJOR_NR, "mcd", &mcd_fops) != 0)
798 {
799 printk("Unable to get major %d for Mitsumi CD-ROM\n", MAJOR_NR);
800 return mem_start;
801 }
802
803 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
804 read_ahead[MAJOR_NR] = 4;
805
806
807
808 outb(0, MCDPORT(1));
809 for (count = 0; count < 1000000; count++)
810 (void) inb(MCDPORT(1));
811
812 outb(0x40, MCDPORT(0));
813 for (count = 0; count < 1000000; count++)
814 if (!(inb(MCDPORT(1)) & MFL_STATUS))
815 break;
816
817 if (count >= 1000000) {
818 printk("mitsumi init failed...\n");
819 return mem_start;
820 }
821 count = inb(MCDPORT(0));
822
823 outb(MCMD_GET_VERSION,MCDPORT(0));
824 for(count=0;count<3;count++)
825 if(getValue(result+count)) {
826 printk("mitsumi get version failed...\n");
827 return mem_start;
828 }
829
830 printk("Mitsumi version : %02X %c %x\n",result[0],result[1],result[2]);
831
832 mcdVersion=result[2];
833
834 if (mcdVersion >=4)
835 outb(4,MCDPORT(2));
836
837
838
839 if (irqaction(MCD_INTR_NR, &mcd_sigaction))
840 {
841 printk("Unable to get IRQ%d for Mitsumi CD-ROM\n", MCD_INTR_NR);
842 return mem_start;
843 }
844
845 mcdPresent = 1;
846 printk("Mitsumi CD-ROM Drive present\n");
847 return mem_start;
848 }
849
850
851 static void
852 hsg2msf(long hsg, struct msf *msf)
853 {
854 hsg += 150;
855 msf -> min = hsg / 4500;
856 hsg %= 4500;
857 msf -> sec = hsg / 75;
858 msf -> frame = hsg % 75;
859
860 bin2bcd(&msf -> min);
861 bin2bcd(&msf -> sec);
862 bin2bcd(&msf -> frame);
863 }
864
865
866 static void
867 bin2bcd(unsigned char *p)
868 {
869 int u, t;
870
871 u = *p % 10;
872 t = *p / 10;
873 *p = u | (t << 4);
874 }
875
876 static int
877 bcd2bin(unsigned char bcd)
878 {
879 return (bcd >> 4) * 10 + (bcd & 0xF);
880 }
881
882
883
884
885
886
887
888 static int
889 mcdStatus(void)
890 {
891 int i;
892 int st;
893
894 st = inb(MCDPORT(1)) & MFL_STATUS;
895 if (!st)
896 {
897 i = inb(MCDPORT(0)) & 0xFF;
898 return i;
899 }
900 else
901 return -1;
902 }
903
904
905
906
907
908
909 static void
910 sendMcdCmd(int cmd, struct mcd_Play_msf *params)
911 {
912 outb(cmd, MCDPORT(0));
913 outb(params -> start.min, MCDPORT(0));
914 outb(params -> start.sec, MCDPORT(0));
915 outb(params -> start.frame, MCDPORT(0));
916 outb(params -> end.min, MCDPORT(0));
917 outb(params -> end.sec, MCDPORT(0));
918 outb(params -> end.frame, MCDPORT(0));
919 }
920
921
922
923
924
925
926
927 static void
928 mcdStatTimer(void)
929 {
930 if (!(inb(MCDPORT(1)) & MFL_STATUS))
931 {
932 wake_up(&mcd_waitq);
933 return;
934 }
935
936 McdTimeout--;
937 if (McdTimeout <= 0)
938 {
939 wake_up(&mcd_waitq);
940 return;
941 }
942
943 SET_TIMER(mcdStatTimer, 1);
944 }
945
946
947
948
949
950
951
952
953 static int
954 getMcdStatus(int timeout)
955 {
956 int st;
957
958 McdTimeout = timeout;
959 SET_TIMER(mcdStatTimer, 1);
960 sleep_on(&mcd_waitq);
961 if (McdTimeout <= 0)
962 return -1;
963
964 st = inb(MCDPORT(0)) & 0xFF;
965 if (st == 0xFF)
966 return -1;
967
968 if ((st & MST_BUSY) == 0 && audioStatus == CDROM_AUDIO_PLAY)
969
970 audioStatus = CDROM_AUDIO_COMPLETED;
971
972 if (st & MST_DSK_CHG)
973 {
974 mcdDiskChanged = 1;
975 tocUpToDate = 0;
976 audioStatus = CDROM_AUDIO_NO_STATUS;
977 }
978
979 return st;
980 }
981
982
983
984
985
986
987
988 static int
989 getValue(unsigned char *result)
990 {
991 int count;
992 int s;
993
994 for (count = 0; count < 2000; count++)
995 if (!(inb(MCDPORT(1)) & MFL_STATUS))
996 break;
997
998 if (count >= 2000)
999 {
1000 printk("mcd: getValue timeout\n");
1001 return -1;
1002 }
1003
1004 s = inb(MCDPORT(0)) & 0xFF;
1005 *result = (unsigned char) s;
1006 return 0;
1007 }
1008
1009
1010
1011
1012
1013
1014
1015 int
1016 GetQChannelInfo(struct mcd_Toc *qp)
1017 {
1018 unsigned char notUsed;
1019 int retry;
1020
1021 for (retry = 0; retry < 3; retry++)
1022 {
1023 outb(MCMD_GET_Q_CHANNEL, MCDPORT(0));
1024 if (getMcdStatus(100) != -1)
1025 break;
1026 }
1027
1028 if (retry >= 3)
1029 return -1;
1030
1031 if (getValue(&qp -> ctrl_addr) < 0) return -1;
1032 if (getValue(&qp -> track) < 0) return -1;
1033 if (getValue(&qp -> pointIndex) < 0) return -1;
1034 if (getValue(&qp -> trackTime.min) < 0) return -1;
1035 if (getValue(&qp -> trackTime.sec) < 0) return -1;
1036 if (getValue(&qp -> trackTime.frame) < 0) return -1;
1037 if (getValue(¬Used) < 0) return -1;
1038 if (getValue(&qp -> diskTime.min) < 0) return -1;
1039 if (getValue(&qp -> diskTime.sec) < 0) return -1;
1040 if (getValue(&qp -> diskTime.frame) < 0) return -1;
1041
1042 return 0;
1043 }
1044
1045
1046
1047
1048
1049
1050 static int
1051 updateToc()
1052 {
1053 if (tocUpToDate)
1054 return 0;
1055
1056 if (GetDiskInfo() < 0)
1057 return -EIO;
1058
1059 if (GetToc() < 0)
1060 return -EIO;
1061
1062 tocUpToDate = 1;
1063 return 0;
1064 }
1065
1066
1067
1068
1069
1070
1071 static int
1072 GetDiskInfo()
1073 {
1074 int retry;
1075
1076 for (retry = 0; retry < 3; retry++)
1077 {
1078 outb(MCMD_GET_DISK_INFO, MCDPORT(0));
1079 if (getMcdStatus(100) != -1)
1080 break;
1081 }
1082
1083 if (retry >= 3)
1084 return -1;
1085
1086 if (getValue(&DiskInfo.first) < 0) return -1;
1087 if (getValue(&DiskInfo.last) < 0) return -1;
1088
1089 DiskInfo.first = bcd2bin(DiskInfo.first);
1090 DiskInfo.last = bcd2bin(DiskInfo.last);
1091
1092 if (getValue(&DiskInfo.diskLength.min) < 0) return -1;
1093 if (getValue(&DiskInfo.diskLength.sec) < 0) return -1;
1094 if (getValue(&DiskInfo.diskLength.frame) < 0) return -1;
1095 if (getValue(&DiskInfo.firstTrack.min) < 0) return -1;
1096 if (getValue(&DiskInfo.firstTrack.sec) < 0) return -1;
1097 if (getValue(&DiskInfo.firstTrack.frame) < 0) return -1;
1098
1099 #ifdef MCD_DEBUG
1100 printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
1101 DiskInfo.first,
1102 DiskInfo.last,
1103 DiskInfo.diskLength.min,
1104 DiskInfo.diskLength.sec,
1105 DiskInfo.diskLength.frame,
1106 DiskInfo.firstTrack.min,
1107 DiskInfo.firstTrack.sec,
1108 DiskInfo.firstTrack.frame);
1109 #endif
1110
1111 return 0;
1112 }
1113
1114
1115
1116
1117
1118
1119 static int
1120 GetToc()
1121 {
1122 int i, px;
1123 int limit;
1124 int retry;
1125 struct mcd_Toc qInfo;
1126
1127 for (i = 0; i < MAX_TRACKS; i++)
1128 Toc[i].pointIndex = 0;
1129
1130 i = DiskInfo.last + 3;
1131
1132 for (retry = 0; retry < 3; retry++)
1133 {
1134 outb(MCMD_STOP, MCDPORT(0));
1135 if (getMcdStatus(100) != -1)
1136 break;
1137 }
1138
1139 if (retry >= 3)
1140 return -1;
1141
1142 for (retry = 0; retry < 3; retry++)
1143 {
1144 outb(MCMD_SET_MODE, MCDPORT(0));
1145 outb(0x05, MCDPORT(0));
1146 if (getMcdStatus(100) != -1)
1147 break;
1148 }
1149
1150 if (retry >= 3)
1151 return -1;
1152
1153 for (limit = 300; limit > 0; limit--)
1154 {
1155 if (GetQChannelInfo(&qInfo) < 0)
1156 break;
1157
1158 px = bcd2bin(qInfo.pointIndex);
1159 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
1160 if (Toc[px].pointIndex == 0)
1161 {
1162 Toc[px] = qInfo;
1163 i--;
1164 }
1165
1166 if (i <= 0)
1167 break;
1168 }
1169
1170 Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
1171
1172 for (retry = 0; retry < 3; retry++)
1173 {
1174 outb(MCMD_SET_MODE, MCDPORT(0));
1175 outb(0x01, MCDPORT(0));
1176 if (getMcdStatus(100) != -1)
1177 break;
1178 }
1179
1180 #ifdef MCD_DEBUG
1181 for (i = 1; i <= DiskInfo.last; i++)
1182 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1183 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1184 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1185 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1186 for (i = 100; i < 103; i++)
1187 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1188 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1189 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1190 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1191 #endif
1192
1193 return limit > 0 ? 0 : -1;
1194 }
1195
1196 #endif