📄 mcd.c.txt
字号:
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: /* Volume control */
441 /*
442 * This is not working yet. Setting the volume by itself does
443 * nothing. Following the 'set' by a 'play' results in zero
444 * volume. Something to work on for the next release.
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: /* Eject the drive - N/A */
480 return 0;
481
482 default:
483 return -EINVAL;
484 }
485 }
486
487
488 /*
489 * Take care of the different block sizes between cdrom and Linux.
490 * When Linux gets variable block sizes this will probably go away.
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 * We only seem to get interrupts after an error.
511 * Just take the interrupt and clear out the status reg.
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 * I/O request routine called from Linux kernel.
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 /* if we satisfied the request from the buffer, we're done. */
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 * Start the I/O for the cdrom. Handle retry count.
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); /* wait a bit, try again */
584 return;
585 }
586
587 McdTries--;
588 outb(0x40, MCDPORT(0)); /* get status */
589 McdTimeout = MCD_STATUS_DELAY;
590 SET_TIMER(mcd_status, 1);
591 }
592
593
594 /*
595 * Called from the timer to check the results of the get-status cmd.
596 * On success, send the set-mode command.
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); /* wait a bit, try again */
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)); /* set mode */
634 outb(0x01, MCDPORT(0)); /* mode = cooked data */
635 McdTimeout = 100;
636 SET_TIMER(mcd_read_cmd, 1);
637 }
638
639
640 /*
641 * Check the result of the set-mode command. On success, send the
642 * read-data command.
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); /* wait a bit, try again */
666 return;
667 }
668
669 SET_TIMER(mcd_read_cmd, 1);
670 return;
671 }
672
673 mcd_bn = -1; /* purge our buffer */
674 block = CURRENT -> sector / 4;
675 hsg2msf(block, &mcdcmd.start); /* cvt to msf format */
676
677 mcdcmd.end.min = 0;
678 mcdcmd.end.sec = 0;
679 mcdcmd.end.frame = 1;
680
681 sendMcdCmd(MCMD_PLAY_READ, &mcdcmd); /* read command */
682 McdTimeout = 200;
683 SET_TIMER(mcd_data, 1);
684 }
685
686
687 /*
688 * Check the completion of the read-data command. On success, read
689 * the 2048 bytes of data from the disk into our buffer.
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 * Open the device special file. Check that a disk is in.
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; /* no hardware */
748
749 st = statusCmd(); /* check drive status */
750 if (st == -1)
751 return -EIO; /* drive doesn't respond */
752
753 if ((st & MST_READY) == 0) /* no disk in drive */
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 * On close, we flush all mcd blocks from the buffer cache.
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, /* lseek - default */
781 block_read, /* read - general block-dev read */
782 block_write, /* write - general block-dev write */
783 NULL, /* readdir - bad */
784 NULL, /* select */
785 mcd_ioctl, /* ioctl */
786 NULL, /* mmap */
787 mcd_open, /* open */
788 mcd_release /* release */
789 };
790
791
792 /*
793 * MCD interrupt descriptor
794 */
795
796 static struct sigaction mcd_sigaction = {
797 mcd_interrupt,
798 0,
799 SA_INTERRUPT,
800 NULL
801 };
802
803
804 /*
805 * Test for presence of drive and initialize it. Called at boot time.
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -