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