⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdu31a.c.txt

📁 Linux块设备驱动分析与模拟实现
💻 TXT
📖 第 1 页 / 共 4 页
字号:
465     * how many more status bytes are coming.
466     *
467     * The result register can be read 10 bytes at a time, a wait for
468     * result ready to be asserted must be done between every 10 bytes.
469     */
470    if ((a & 0xf0) != 0x20)
471    {
472       if (b > 8)
473       {
474          for (i=0; i<8; i++)
475          {
476             *result_buffer = read_result_register();
477             result_buffer++;
478             (*result_size)++;
479          }
480          b = b - 8;
481 
482          while (b > 10)
483          {
484             retry_count = SONY_READY_RETRIES;
485             while ((retry_count > 0) && (!is_result_ready()))
486             {
487                retry_count--;
488             }
489             if (!is_result_ready())
490             {
491                result_buffer[0] = 0x20;
492                result_buffer[1] = SONY_TIMEOUT_OP_ERR;
493                *result_size = 2;
494                return;
495             }
496 
497             clear_result_ready();
498                                 
499             for (i=0; i<10; i++)
500             {
501                *result_buffer = read_result_register();
502                result_buffer++;
503                (*result_size)++;
504             }
505             b = b - 10;
506          }
507 
508          if (b > 0)
509          {
510             retry_count = SONY_READY_RETRIES;
511             while ((retry_count > 0) && (!is_result_ready()))
512             {
513                retry_count--;
514             }
515             if (!is_result_ready())
516             {
517                result_buffer[0] = 0x20;
518                result_buffer[1] = SONY_TIMEOUT_OP_ERR;
519                *result_size = 2;
520                return;
521             }
522          }
523       }
524 
525       while (b > 0)
526       {
527          *result_buffer = read_result_register();
528          result_buffer++;
529          (*result_size)++;
530          b--;
531       }
532    }
533 }
534 
535 /*
536  * Read in a 2048 byte block of data.
537  */
538 static void
539 read_data_block(unsigned char *data,
540                 unsigned char *result_buffer,
541                 unsigned int  *result_size)
542 {
543    int i;
544    unsigned int retry_count;
545 
546    for (i=0; i<2048; i++)
547    {
548       retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
549       while ((retry_count > jiffies) && (!is_data_requested()))
550       {
551          while (handle_sony_cd_attention())
552             ;
553          
554          sony_sleep();
555       }
556       if (!is_data_requested())
557       {
558          result_buffer[0] = 0x20;
559          result_buffer[1] = SONY_TIMEOUT_OP_ERR;
560          *result_size = 2;
561          return;
562       }
563       
564       *data = read_data_register();
565       data++;
566    }
567 }
568 
569 /*
570  * This routine issues a read data command and gets the data.  I don't
571  * really like the way this is done (I would prefer for do_sony_cmd() to
572  * handle it automatically) but I found that the drive returns status
573  * when it finishes reading (not when the host has read all the data)
574  * or after it gets an error.  This means that the status can be
575  * received at any time and should be handled immediately (at least
576  * between every 2048 byte block) to check for errors, we can't wait
577  * until all the data is read.
578  *
579  * This routine returns the total number of sectors read.  It will
580  * not return an error if it reads at least one sector successfully.
581  */
582 static unsigned int
583 get_data(unsigned char *orig_data,
584          unsigned char *params,         /* 6 bytes with the MSF start address
585                                            and number of sectors to read. */
586          unsigned int orig_data_size,
587          unsigned char *result_buffer,
588          unsigned int *result_size)
589 {
590    unsigned int cur_offset;
591    unsigned int retry_count;
592    int result_read;
593    int num_retries;
594    unsigned int num_sectors_read = 0;
595    unsigned char *data = orig_data;
596    unsigned int data_size = orig_data_size;
597 
598 
599    cli();
600    while (sony_inuse)
601    {
602       interruptible_sleep_on(&sony_wait);
603       if (current->signal & ~current->blocked)
604       {
605          result_buffer[0] = 0x20;
606          result_buffer[1] = SONY_SIGNAL_OP_ERR;
607          *result_size = 2;
608          return 0;
609       }
610    }
611    sony_inuse = 1;
612    has_cd_task = current;
613    sti();
614 
615    num_retries = 0;
616 retry_data_operation:
617    result_buffer[0] = 0;
618    result_buffer[1] = 0;
619 
620    /*
621     * Clear any outstanding attentions and wait for the drive to
622     * complete any pending operations.
623     */
624    while (handle_sony_cd_attention())
625       ;
626 
627    retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
628    while ((retry_count > jiffies) && (is_busy()))
629    {
630       sony_sleep();
631       
632       while (handle_sony_cd_attention())
633          ;
634    }
635 
636    if (is_busy())
637    {
638       result_buffer[0] = 0x20;
639       result_buffer[1] = SONY_TIMEOUT_OP_ERR;
640       *result_size = 2;
641    }
642    else
643    {
644       /* Issue the command */
645       clear_result_ready();
646       clear_param_reg();
647 
648       write_params(params, 6);
649       write_cmd(SONY_READ_CMD);
650 
651       /*
652        * Read the data from the drive one 2048 byte sector at a time.  Handle
653        * any results received between sectors, if an error result is returned
654        * terminate the operation immediately.
655        */
656       cur_offset = 0;
657       result_read = 0;
658       while ((data_size > 0) && (result_buffer[0] == 0))
659       {
660          /* Wait for the drive to tell us we have something */
661          retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
662          while ((retry_count > jiffies) && (!(is_result_ready() || is_data_ready())))
663          {
664             while (handle_sony_cd_attention())
665                ;
666 
667             sony_sleep();
668          }
669          if (!(is_result_ready() || is_data_ready()))
670          {
671             result_buffer[0] = 0x20;
672             result_buffer[1] = SONY_TIMEOUT_OP_ERR;
673             *result_size = 2;
674          }
675       
676          /* Handle results first */
677          else if (is_result_ready())
678          {
679             result_read = 1;
680             get_result(result_buffer, result_size);
681          }
682          else /* Handle data next */
683          {
684             /*
685              * The drive has to be polled for status on a byte-by-byte basis
686              * to know if the data is ready.  Yuck.  I really wish I could use DMA.
687              */
688             clear_data_ready();
689             read_data_block(data, result_buffer, result_size);
690             data += 2048;
691             data_size -= 2048;
692             cur_offset = cur_offset + 2048;
693             num_sectors_read++;
694          }
695       }
696 
697       /* Make sure the result has been read */
698       if (!result_read)
699       {
700          get_result(result_buffer, result_size);
701       }
702    }
703 
704    if (   ((result_buffer[0] & 0x20) == 0x20)
705        && (result_buffer[1] != SONY_NOT_SPIN_ERR) /* No retry when not spin */
706        && (num_retries < MAX_CDU31A_RETRIES))
707    {
708       /*
709        * If an error occurs, go back and only read one sector at the
710        * given location.  Hopefully the error occurred on an unused
711        * sector after the first one.  It is hard to say which sector
712        * the error occurred on because the drive returns status before
713        * the data transfer is finished and doesn't say which sector.
714        */
715       data_size = 2048;
716       data = orig_data;
717       num_sectors_read = 0;
718       size_to_buf(1, &params[3]);
719 
720       num_retries++;
721       /* Issue a reset on an error (the second time), othersize just delay */
722       if (num_retries == 2)
723       {
724          restart_on_error();
725       }
726       else
727       {
728          current->state = TASK_INTERRUPTIBLE;
729          current->timeout = jiffies + 10;
730          schedule();
731       }
732 
733       /* Restart the operation. */
734       goto retry_data_operation;
735    }
736 
737    has_cd_task = NULL;
738    sony_inuse = 0;
739    wake_up_interruptible(&sony_wait);
740 
741    return(num_sectors_read);
742 }
743 
744 
745 /*
746  * Do a command that does not involve data transfer.  This routine must
747  * be re-entrant from the same task to support being called from the
748  * data operation code when an error occurs.
749  */
750 static void
751 do_sony_cd_cmd(unsigned char cmd,
752                unsigned char *params,
753                unsigned int num_params,
754                unsigned char *result_buffer,
755                unsigned int *result_size)
756 {
757    unsigned int retry_count;
758    int num_retries;
759    int recursive_call;
760 
761 
762    cli();
763    if (current != has_cd_task) /* Allow recursive calls to this routine */
764    {
765       while (sony_inuse)
766       {
767          interruptible_sleep_on(&sony_wait);
768          if (current->signal & ~current->blocked)
769          {
770             result_buffer[0] = 0x20;
771             result_buffer[1] = SONY_SIGNAL_OP_ERR;
772             *result_size = 2;
773             return;
774          }
775       }
776       sony_inuse = 1;
777       has_cd_task = current;
778       recursive_call = 0;
779    }
780    else
781    {
782       recursive_call = 1;
783    }
784    sti();
785 
786    num_retries = 0;
787 retry_cd_operation:
788 
789    while (handle_sony_cd_attention())
790       ;
791    
792    retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
793    while ((retry_count > jiffies) && (is_busy()))
794    {
795       sony_sleep();
796       
797       while (handle_sony_cd_attention())
798          ;
799    }
800    if (is_busy())
801    {
802       result_buffer[0] = 0x20;
803       result_buffer[1] = SONY_TIMEOUT_OP_ERR;
804       *result_size = 2;
805    }
806    else
807    {
808       clear_result_ready();
809       clear_param_reg();
810 
811       write_params(params, num_params);
812       write_cmd(cmd);
813 
814       get_result(result_buffer, result_size);
815    }
816 
817    if (   ((result_buffer[0] & 0x20) == 0x20)
818        && (num_retries < MAX_CDU31A_RETRIES))
819    {
820       num_retries++;
821       current->state = TASK_INTERRUPTIBLE;
822       current->timeout = jiffies + 10; /* Wait .1 seconds on retries */
823       schedule();
824       goto retry_cd_operation;
825    }
826 
827    if (!recursive_call)
828    {
829       has_cd_task = NULL;
830       sony_inuse = 0;
831       wake_up_interruptible(&sony_wait);
832    }
833 }
834 
835 
836 /*
837  * Handle an attention from the drive.  This will return 1 if it found one
838  * or 0 if not (if one is found, the caller might want to call again).
839  *
840  * This routine counts the number of consecutive times it is called
841  * (since this is always called from a while loop until it returns
842  * a 0), and returns a 0 if it happens too many times.  This will help
843  * prevent a lockup.
844  */
845 static int
846 handle_sony_cd_attention(void)
847 {
848    unsigned char atten_code;
849    static int num_consecutive_attentions = 0;
850 
851 
852    if (is_attention())
853    {
854       if (num_consecutive_attentions > CDU31A_MAX_CONSECUTIVE_ATTENTIONS)
855       {
856          printk("cdu31a: Too many consecutive attentions: %d\n",
857                 num_consecutive_attentions);
858          num_consecutive_attentions = 0;
859          return(0);
860       }
861 
862       clear_attention();
863       atten_code = read_result_register();
864 
865       switch (atten_code)
866       {
867        /* Someone changed the CD.  Mark it as changed */
868       case SONY_MECH_LOADED_ATTN:
869          sony_disc_changed = 1;
870          sony_toc_read = 0;
871          sony_audio_status = CDROM_AUDIO_NO_STATUS;
872          sony_first_block = -1;
873          sony_last_block = -1;
874          break;
875 
876       case SONY_AUDIO_PLAY_DONE_ATTN:
877          sony_audio_status = CDROM_AUDIO_COMPLETED;
878          read_subcode();
879          break;
880 
881       case SONY_EJECT_PUSHED_ATTN:
882          sony_audio_status = CDROM_AUDIO_INVALID;
883          break;
884 
885       case SONY_LEAD_IN_ERR_ATTN:
886       case SONY_LEAD_OUT_ERR_ATTN:
887       case SONY_DATA_TRACK_ERR_ATTN:
888       case SONY_AUDIO_PLAYBACK_ERR_ATTN:
889          sony_audio_status = CDROM_AUDIO_ERROR;
890          break;
891       }
892 
893       num_consecutive_attentions++;
894       return(1);
895    }
896 
897    num_consecutive_attentions = 0;
898    return(0);
899 }
900 
901 
902 /* Convert from an integer 0-99 to BCD */
903 static inline unsigned int
904 int_to_bcd(unsigned int val)
905 {
906    int retval;
907 
908 
909    retval = (val / 10) << 4;
910    retval = retval | val % 10;
911    return(retval);
912 }
913 
914 
915 /* Convert from BCD to an integer from 0-99 */
916 static unsigned int
917 bcd_to_int(unsigned int bcd)
918 {
919    return((((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f));
920 }
921 
922 
923 /*
924  * Convert a logical sector value (like the OS would want to use for
925  * a block device) to an MSF format.
926  */
927 static void
928 log_to_msf(unsigned int log, unsigned char *msf)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -