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 printk("mcd: Mitsumi version : %02X %c %x\n",
857 result[0],result[1],result[2]);
858
859
860 mcdVersion=result[2];
861
862 if (mcdVersion >=4)
863 outb(4,MCDPORT(2));
864
865
866
867 if (irqaction(MCD_INTR_NR, &mcd_sigaction))
868 {
869 printk("mcd: Unable to get IRQ%d for Mitsumi CD-ROM\n", MCD_INTR_NR);
870 return mem_start;
871 }
872 snarf_region(mcd_port, 4);
873 mcdPresent = 1;
874 printk("mcd: Mitsumi CD-ROM Drive present at addr %x, irq %d\n",
875 mcd_port, mcd_irq);
876 return mem_start;
877 }
878
879
880 static void
881 hsg2msf(long hsg, struct msf *msf)
882 {
883 hsg += 150;
884 msf -> min = hsg / 4500;
885 hsg %= 4500;
886 msf -> sec = hsg / 75;
887 msf -> frame = hsg % 75;
888
889 bin2bcd(&msf -> min);
890 bin2bcd(&msf -> sec);
891 bin2bcd(&msf -> frame);
892 }
893
894
895 static void
896 bin2bcd(unsigned char *p)
897 {
898 int u, t;
899
900 u = *p % 10;
901 t = *p / 10;
902 *p = u | (t << 4);
903 }
904
905 static int
906 bcd2bin(unsigned char bcd)
907 {
908 return (bcd >> 4) * 10 + (bcd & 0xF);
909 }
910
911
912
913
914
915
916
917 static int
918 mcdStatus(void)
919 {
920 int i;
921 int st;
922
923 st = inb(MCDPORT(1)) & MFL_STATUS;
924 if (!st)
925 {
926 i = inb(MCDPORT(0)) & 0xFF;
927 return i;
928 }
929 else
930 return -1;
931 }
932
933
934
935
936
937
938 static void
939 sendMcdCmd(int cmd, struct mcd_Play_msf *params)
940 {
941 outb(cmd, MCDPORT(0));
942 outb(params -> start.min, MCDPORT(0));
943 outb(params -> start.sec, MCDPORT(0));
944 outb(params -> start.frame, MCDPORT(0));
945 outb(params -> end.min, MCDPORT(0));
946 outb(params -> end.sec, MCDPORT(0));
947 outb(params -> end.frame, MCDPORT(0));
948 }
949
950
951
952
953
954
955
956 static void
957 mcdStatTimer(void)
958 {
959 if (!(inb(MCDPORT(1)) & MFL_STATUS))
960 {
961 wake_up(&mcd_waitq);
962 return;
963 }
964
965 McdTimeout--;
966 if (McdTimeout <= 0)
967 {
968 wake_up(&mcd_waitq);
969 return;
970 }
971
972 SET_TIMER(mcdStatTimer, 1);
973 }
974
975
976
977
978
979
980
981
982 static int
983 getMcdStatus(int timeout)
984 {
985 int st;
986
987 McdTimeout = timeout;
988 SET_TIMER(mcdStatTimer, 1);
989 sleep_on(&mcd_waitq);
990 if (McdTimeout <= 0)
991 return -1;
992
993 st = inb(MCDPORT(0)) & 0xFF;
994 if (st == 0xFF)
995 return -1;
996
997 if ((st & MST_BUSY) == 0 && audioStatus == CDROM_AUDIO_PLAY)
998
999 audioStatus = CDROM_AUDIO_COMPLETED;
1000
1001 if (st & MST_DSK_CHG)
1002 {
1003 mcdDiskChanged = 1;
1004 tocUpToDate = 0;
1005 audioStatus = CDROM_AUDIO_NO_STATUS;
1006 }
1007
1008 return st;
1009 }
1010
1011
1012
1013
1014
1015
1016
1017 static int
1018 getValue(unsigned char *result)
1019 {
1020 int count;
1021 int s;
1022
1023 for (count = 0; count < 2000; count++)
1024 if (!(inb(MCDPORT(1)) & MFL_STATUS))
1025 break;
1026
1027 if (count >= 2000)
1028 {
1029 printk("mcd: getValue timeout\n");
1030 return -1;
1031 }
1032
1033 s = inb(MCDPORT(0)) & 0xFF;
1034 *result = (unsigned char) s;
1035 return 0;
1036 }
1037
1038
1039
1040
1041
1042
1043
1044 int
1045 GetQChannelInfo(struct mcd_Toc *qp)
1046 {
1047 unsigned char notUsed;
1048 int retry;
1049
1050 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1051 {
1052 outb(MCMD_GET_Q_CHANNEL, MCDPORT(0));
1053 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1054 break;
1055 }
1056
1057 if (retry >= MCD_RETRY_ATTEMPTS)
1058 return -1;
1059
1060 if (getValue(&qp -> ctrl_addr) < 0) return -1;
1061 if (getValue(&qp -> track) < 0) return -1;
1062 if (getValue(&qp -> pointIndex) < 0) return -1;
1063 if (getValue(&qp -> trackTime.min) < 0) return -1;
1064 if (getValue(&qp -> trackTime.sec) < 0) return -1;
1065 if (getValue(&qp -> trackTime.frame) < 0) return -1;
1066 if (getValue(¬Used) < 0) return -1;
1067 if (getValue(&qp -> diskTime.min) < 0) return -1;
1068 if (getValue(&qp -> diskTime.sec) < 0) return -1;
1069 if (getValue(&qp -> diskTime.frame) < 0) return -1;
1070
1071 return 0;
1072 }
1073
1074
1075
1076
1077
1078
1079 static int
1080 updateToc()
1081 {
1082 if (tocUpToDate)
1083 return 0;
1084
1085 if (GetDiskInfo() < 0)
1086 return -EIO;
1087
1088 if (GetToc() < 0)
1089 return -EIO;
1090
1091 tocUpToDate = 1;
1092 return 0;
1093 }
1094
1095
1096
1097
1098
1099
1100 static int
1101 GetDiskInfo()
1102 {
1103 int retry;
1104
1105 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1106 {
1107 outb(MCMD_GET_DISK_INFO, MCDPORT(0));
1108 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1109 break;
1110 }
1111
1112 if (retry >= MCD_RETRY_ATTEMPTS)
1113 return -1;
1114
1115 if (getValue(&DiskInfo.first) < 0) return -1;
1116 if (getValue(&DiskInfo.last) < 0) return -1;
1117
1118 DiskInfo.first = bcd2bin(DiskInfo.first);
1119 DiskInfo.last = bcd2bin(DiskInfo.last);
1120
1121 if (getValue(&DiskInfo.diskLength.min) < 0) return -1;
1122 if (getValue(&DiskInfo.diskLength.sec) < 0) return -1;
1123 if (getValue(&DiskInfo.diskLength.frame) < 0) return -1;
1124 if (getValue(&DiskInfo.firstTrack.min) < 0) return -1;
1125 if (getValue(&DiskInfo.firstTrack.sec) < 0) return -1;
1126 if (getValue(&DiskInfo.firstTrack.frame) < 0) return -1;
1127
1128 #ifdef MCD_DEBUG
1129 printk("Disk Info: first %d last %d length %02x:%02x.%02x first %02x:%02x.%02x\n",
1130 DiskInfo.first,
1131 DiskInfo.last,
1132 DiskInfo.diskLength.min,
1133 DiskInfo.diskLength.sec,
1134 DiskInfo.diskLength.frame,
1135 DiskInfo.firstTrack.min,
1136 DiskInfo.firstTrack.sec,
1137 DiskInfo.firstTrack.frame);
1138 #endif
1139
1140 return 0;
1141 }
1142
1143
1144
1145
1146
1147
1148 static int
1149 GetToc()
1150 {
1151 int i, px;
1152 int limit;
1153 int retry;
1154 struct mcd_Toc qInfo;
1155
1156 for (i = 0; i < MAX_TRACKS; i++)
1157 Toc[i].pointIndex = 0;
1158
1159 i = DiskInfo.last + 3;
1160
1161 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1162 {
1163 outb(MCMD_STOP, MCDPORT(0));
1164 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1165 break;
1166 }
1167
1168 if (retry >= MCD_RETRY_ATTEMPTS)
1169 return -1;
1170
1171 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1172 {
1173 outb(MCMD_SET_MODE, MCDPORT(0));
1174 outb(0x05, MCDPORT(0));
1175 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1176 break;
1177 }
1178
1179 if (retry >= MCD_RETRY_ATTEMPTS)
1180 return -1;
1181
1182 for (limit = 300; limit > 0; limit--)
1183 {
1184 if (GetQChannelInfo(&qInfo) < 0)
1185 break;
1186
1187 px = bcd2bin(qInfo.pointIndex);
1188 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
1189 if (Toc[px].pointIndex == 0)
1190 {
1191 Toc[px] = qInfo;
1192 i--;
1193 }
1194
1195 if (i <= 0)
1196 break;
1197 }
1198
1199 Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
1200
1201 for (retry = 0; retry < MCD_RETRY_ATTEMPTS; retry++)
1202 {
1203 outb(MCMD_SET_MODE, MCDPORT(0));
1204 outb(0x01, MCDPORT(0));
1205 if (getMcdStatus(MCD_STATUS_DELAY) != -1)
1206 break;
1207 }
1208
1209 #ifdef MCD_DEBUG
1210 for (i = 1; i <= DiskInfo.last; i++)
1211 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1212 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1213 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1214 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1215 for (i = 100; i < 103; i++)
1216 printk("i = %2d ctl-adr = %02X track %2d px %02X %02X:%02X.%02X %02X:%02X.%02X\n",
1217 i, Toc[i].ctrl_addr, Toc[i].track, Toc[i].pointIndex,
1218 Toc[i].trackTime.min, Toc[i].trackTime.sec, Toc[i].trackTime.frame,
1219 Toc[i].diskTime.min, Toc[i].diskTime.sec, Toc[i].diskTime.frame);
1220 #endif
1221
1222 return limit > 0 ? 0 : -1;
1223 }
1224