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
34 #include <linux/errno.h>
35 #include <linux/signal.h>
36 #include <linux/sched.h>
37 #include <linux/timer.h>
38 #include <linux/fs.h>
39 #include <linux/kernel.h>
40 #include <linux/cdrom.h>
41
42
43 #include <asm/system.h>
44 #include <asm/io.h>
45 #include <asm/segment.h>
46
47 #define MAJOR_NR MITSUMI_CDROM_MAJOR
48 #include "blk.h"
49
50 #include <linux/mcd.h>
51
52 #if 0
53 static int mcd_sizes[] = { 0 };
54 #endif
55
56 static int mcdPresent = 0;
57
58 static char mcd_buf[2048];
59 static int mcd_bn = -1;
60
61 static int McdTimeout, McdTries;
62 static struct wait_queue *mcd_waitq = NULL;
63
64 static struct mcd_DiskInfo DiskInfo;
65 static struct mcd_Toc Toc[MAX_TRACKS];
66 static struct mcd_Play_msf mcd_Play;
67
68 static int audioStatus;
69 static char mcdDiskChanged;
70 static char tocUpToDate;
71 static char mcdVersion;
72
73 static void mcd_transfer(void);
74 static void mcd_start(void);
75 static void mcd_status(void);
76 static void mcd_read_cmd(void);
77 static void mcd_data(void);
78 static void do_mcd_request(void);
79 static void hsg2msf(long hsg, struct msf *msf);
80 static void bin2bcd(unsigned char *p);
81 static int bcd2bin(unsigned char bcd);
82 static int mcdStatus(void);
83 static void sendMcdCmd(int cmd, struct mcd_Play_msf *params);
84 static int getMcdStatus(int timeout);
85 static int GetQChannelInfo(struct mcd_Toc *qp);
86 static int updateToc(void);
87 static int GetDiskInfo(void);
88 static int GetToc(void);
89 static int getValue(unsigned char *result);
90
91
92 int
93 check_mcd_media_change(int full_dev, int flag)
94 {
95 int retval, target;
96
97
98 target = MINOR(full_dev);
99
100 if (target > 0) {
101 printk("Mitsumi CD-ROM request error: invalid device.\n");
102 return 0;
103 }
104
105 retval = mcdDiskChanged;
106 if (!flag)
107 {
108 mcdDiskChanged = 0;
109 }
110
111 return retval;
112 }
113
114
115
116
117
118
119
120 static int
121 statusCmd(void)
122 {
123 int st, retry;
124
125 for (retry = 0; retry < 3; retry++)
126 {
127 outb(MCMD_GET_STATUS, MCDPORT(0));
128 st = getMcdStatus(100);
129 if (st != -1)
130 break;
131 }
132
133 return st;
134 }
135
136
137
138
139
140
141 static int
142 mcdPlay(struct mcd_Play_msf *arg)
143 {
144 int retry, st;
145
146 for (retry = 0; retry < 3; retry++)
147 {
148 sendMcdCmd(MCMD_PLAY_READ, arg);
149 st = getMcdStatus(200);
150 if (st != -1)
151 break;
152 }
153
154 return st;
155 }
156
157
158 long
159 msf2hsg(struct msf *mp)
160 {
161 return bcd2bin(mp -> frame)
162 + bcd2bin(mp -> sec) * 75
163 + bcd2bin(mp -> min) * 4500
164 - 150;
165 }
166
167
168 static int
169 mcd_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
170 unsigned long arg)
171 {
172 int i, st;
173 struct mcd_Toc qInfo;
174 struct cdrom_ti ti;
175 struct cdrom_tochdr tocHdr;
176 struct cdrom_msf msf;
177 struct cdrom_tocentry entry;
178 struct mcd_Toc *tocPtr;
179 struct cdrom_subchnl subchnl;
180 #if 0
181 struct cdrom_volctrl volctrl;
182 #endif
183
184 if (!ip)
185 return -EINVAL;
186
187 st = statusCmd();
188 if (st < 0)
189 return -EIO;
190
191 if (!tocUpToDate)
192 {
193 i = updateToc();
194 if (i < 0)
195 return i;
196 }
197
198 switch (cmd)
199 {
200 case CDROMSTART:
201
202
203
204
205
206 return 0;
207
208 case CDROMSTOP:
209 outb(MCMD_STOP, MCDPORT(0));
210 i = getMcdStatus(100);
211
212
213
214 audioStatus = CDROM_AUDIO_NO_STATUS;
215 return 0;
216
217 case CDROMPAUSE:
218 if (audioStatus != CDROM_AUDIO_PLAY)
219 return -EINVAL;
220
221 outb(MCMD_STOP, MCDPORT(0));
222 i = getMcdStatus(100);
223
224 if (GetQChannelInfo(&qInfo) < 0)
225 {
226
227
228 audioStatus = CDROM_AUDIO_NO_STATUS;
229 return 0;
230 }
231
232 mcd_Play.start = qInfo.diskTime;
233
234 audioStatus = CDROM_AUDIO_PAUSED;
235 return 0;
236
237 case CDROMRESUME:
238 if (audioStatus != CDROM_AUDIO_PAUSED)
239 return -EINVAL;
240
241
242
243 i = mcdPlay(&mcd_Play);
244 if (i < 0)
245 {
246 audioStatus = CDROM_AUDIO_ERROR;
247 return -EIO;
248 }
249
250 audioStatus = CDROM_AUDIO_PLAY;
251 return 0;
252
253 case CDROMPLAYTRKIND:
254
255 st = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
256 if (st)
257 return st;
258
259 memcpy_fromfs(&ti, (void *) arg, sizeof ti);
260
261 if (ti.cdti_trk0 < DiskInfo.first
262 || ti.cdti_trk0 > DiskInfo.last
263 || ti.cdti_trk1 < ti.cdti_trk0)
264 {
265 return -EINVAL;
266 }
267
268 if (ti.cdti_trk1 > DiskInfo.last)
269 ti. cdti_trk1 = DiskInfo.last;
270
271 mcd_Play.start = Toc[ti.cdti_trk0].diskTime;
272 mcd_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
273
274 #ifdef MCD_DEBUG
275 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
276 mcd_Play.start.min, mcd_Play.start.sec, mcd_Play.start.frame,
277 mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame);
278 #endif
279
280 i = mcdPlay(&mcd_Play);
281 if (i < 0)
282 {
283 audioStatus = CDROM_AUDIO_ERROR;
284 return -EIO;
285 }
286
287 audioStatus = CDROM_AUDIO_PLAY;
288 return 0;
289
290 case CDROMPLAYMSF:
291
292 if (audioStatus == CDROM_AUDIO_PLAY) {
293 outb(MCMD_STOP, MCDPORT(0));
294 i = getMcdStatus(100);
295 audioStatus = CDROM_AUDIO_NO_STATUS;
296 }
297
298 st = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
299 if (st)
300 return st;
301
302 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
303
304
305
306 bin2bcd(&msf.cdmsf_min0);
307 bin2bcd(&msf.cdmsf_sec0);
308 bin2bcd(&msf.cdmsf_frame0);
309 bin2bcd(&msf.cdmsf_min1);
310 bin2bcd(&msf.cdmsf_sec1);
311 bin2bcd(&msf.cdmsf_frame1);
312
313 mcd_Play.start.min = msf.cdmsf_min0;
314 mcd_Play.start.sec = msf.cdmsf_sec0;
315 mcd_Play.start.frame = msf.cdmsf_frame0;
316 mcd_Play.end.min = msf.cdmsf_min1;
317 mcd_Play.end.sec = msf.cdmsf_sec1;
318 mcd_Play.end.frame = msf.cdmsf_frame1;
319
320 #ifdef MCD_DEBUG
321 printk("play: %02x:%02x.%02x to %02x:%02x.%02x\n",
322 mcd_Play.start.min, mcd_Play.start.sec, mcd_Play.start.frame,
323 mcd_Play.end.min, mcd_Play.end.sec, mcd_Play.end.frame);
324 #endif
325
326 i = mcdPlay(&mcd_Play);
327 if (i < 0)
328 {
329 audioStatus = CDROM_AUDIO_ERROR;
330 return -EIO;
331 }
332
333 audioStatus = CDROM_AUDIO_PLAY;
334 return 0;
335
336 case CDROMREADTOCHDR:
337 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof tocHdr);
338 if (st)
339 return st;
340
341 tocHdr.cdth_trk0 = DiskInfo.first;
342 tocHdr.cdth_trk1 = DiskInfo.last;
343 memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr);
344 return 0;
345
346 case CDROMREADTOCENTRY:
347
348 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
349 if (st)
350 return st;
351
352 memcpy_fromfs(&entry, (void *) arg, sizeof entry);
353 if (entry.cdte_track == CDROM_LEADOUT)
354
355 tocPtr = &Toc[DiskInfo.last + 1];
356
357 else if (entry.cdte_track > DiskInfo.last
358 || entry.cdte_track < DiskInfo.first)
359 return -EINVAL;
360
361 else
362 tocPtr = &Toc[entry.cdte_track];
363
364 entry.cdte_adr = tocPtr -> ctrl_addr;
365 entry.cdte_ctrl = tocPtr -> ctrl_addr >> 4;
366
367 if (entry.cdte_format == CDROM_LBA)
368 entry.cdte_addr.lba = msf2hsg(&tocPtr -> diskTime);
369
370 else if (entry.cdte_format == CDROM_MSF)
371 {
372 entry.cdte_addr.msf.minute = bcd2bin(tocPtr -> diskTime.min);
373 entry.cdte_addr.msf.second = bcd2bin(tocPtr -> diskTime.sec);
374 entry.cdte_addr.msf.frame = bcd2bin(tocPtr -> diskTime.frame);
375 }
376
377 else
378 return -EINVAL;
379
380 memcpy_tofs((void *) arg, &entry, sizeof entry);
381 return 0;
382
383 case CDROMSUBCHNL:
384
385 st = verify_area(VERIFY_WRITE, (void *) arg, sizeof subchnl);
386 if (st)
387 return st;
388
389 memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
390
391 if (GetQChannelInfo(&qInfo) < 0)
392 return -EIO;
393
394 subchnl.cdsc_audiostatus = audioStatus;
395 subchnl.cdsc_adr = qInfo.ctrl_addr;
396 subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
397 subchnl.cdsc_trk = bcd2bin(qInfo.track);
398 subchnl.cdsc_ind = bcd2bin(qInfo.pointIndex);
399
400 if (subchnl.cdsc_format == CDROM_LBA)
401 {
402 subchnl.cdsc_absaddr.lba = msf2hsg(&qInfo.diskTime);
403 subchnl.cdsc_reladdr.lba = msf2hsg(&qInfo.trackTime);
404 }
405
406 else if (subchnl.cdsc_format == CDROM_MSF)
407 {
408 subchnl.cdsc_absaddr.msf.minute = bcd2bin(qInfo.diskTime.min);
409 subchnl.cdsc_absaddr.msf.second = bcd2bin(qInfo.diskTime.sec);
410 subchnl.cdsc_absaddr.msf.frame = bcd2bin(qInfo.diskTime.frame);
411
412 subchnl.cdsc_reladdr.msf.minute = bcd2bin(qInfo.trackTime.min);
413 subchnl.cdsc_reladdr.msf.second = bcd2bin(qInfo.trackTime.sec);
414 subchnl.cdsc_reladdr.msf.frame = bcd2bin(qInfo.trackTime.frame);
415 }
416
417 else
418 return -EINVAL;
419
420 memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
421 return 0;
422
423 case CDROMVOLCTRL:
424
425
426
427
428
429 #if 0
430 st = verify_area(VERIFY_READ, (void *) arg, sizeof(volctrl));
431 if (st)
432 return st;
433
434 memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
435 printk("VOL %d %d\n", volctrl.channel0 & 0xFF, volctrl.channel1 & 0xFF);
436 outb(MCMD_SET_VOLUME, MCDPORT(0));
437 outb(volctrl.channel0, MCDPORT(0));
438 outb(0, MCDPORT(0));
439 outb(volctrl.channel1, MCDPORT(0));
440 outb(1, MCDPORT(0));
441
442 i = getMcdStatus(100);
443 if (i < 0)
444 return -EIO;
445
446 {
447 int a, b, c, d;
448
449 getValue(&a);
450 getValue(&b);
451 getValue(&c);
452 getValue(&d);
453 printk("%02X %02X %02X %02X\n", a, b, c, d);
454 }
455
456 outb(0xF8, MCDPORT(0));
457 i = getMcdStatus(100);
458 printk("F8 -> %02X\n", i & 0xFF);
459 #endif
460 return 0;
461
462 case CDROMEJECT:
463 return 0;
464
465 default:
466 return -EINVAL;
467 }
468 }
469
470
471
472
473
474
475
476 static void
477 mcd_transfer(void)
478 {
479 long offs;
480
481 while (CURRENT -> nr_sectors > 0 && mcd_bn == CURRENT -> sector / 4)
482 {
483 offs = (CURRENT -> sector & 3) * 512;
484 memcpy(CURRENT -> buffer, mcd_buf + offs, 512);
485 CURRENT -> nr_sectors--;
486 CURRENT -> sector++;
487 CURRENT -> buffer += 512;
488 }
489 }
490
491
492
493
494
495
496
497 static void
498 mcd_interrupt(int unused)
499 {
500 int st;
501
502 st = inb(MCDPORT(1)) & 0xFF;
503 if (st != 0xFF)
504 {
505 st = inb(MCDPORT(0)) & 0xFF;
506 #if 0
507 printk("<int-%02X>", st);
508 #endif
509 }
510 }
511
512
513
514
515
516
517 static void
518 do_mcd_request(void)
519 {
520 unsigned int block,dev;
521 unsigned int nsect;
522
523 repeat:
524 if (!(CURRENT) || CURRENT->dev < 0) return;
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