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

📄 cdu31a.c

📁 powerpc内核 mpc8241芯片 linux系统下cdrom驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
         *result_buffer = read_result_register();         result_buffer++;         (*result_size)++;         b--;      }   }}/* * Do a command that does not involve data transfer.  This routine must * be re-entrant from the same task to support being called from the * data operation code when an error occurs. */static voiddo_sony_cd_cmd(unsigned char cmd,               unsigned char *params,               unsigned int num_params,               unsigned char *result_buffer,               unsigned int *result_size){   unsigned int retry_count;   int num_retries;   int recursive_call;   unsigned long flags;   save_flags(flags);   cli();   if (current != has_cd_task) /* Allow recursive calls to this routine */   {      while (sony_inuse)      {         interruptible_sleep_on(&sony_wait);         if (signal_pending(current))         {            result_buffer[0] = 0x20;            result_buffer[1] = SONY_SIGNAL_OP_ERR;            *result_size = 2;            restore_flags(flags);            return;         }      }      sony_inuse = 1;      has_cd_task = current;      recursive_call = 0;   }   else   {      recursive_call = 1;   }   num_retries = 0;retry_cd_operation:   while (handle_sony_cd_attention())      ;   sti();      retry_count = jiffies + SONY_JIFFIES_TIMEOUT;   while (time_before(jiffies, retry_count) && (is_busy()))   {      sony_sleep();            while (handle_sony_cd_attention())         ;   }   if (is_busy())   {#if DEBUG      printk("CDU31A timeout out %d\n", __LINE__);#endif      result_buffer[0] = 0x20;      result_buffer[1] = SONY_TIMEOUT_OP_ERR;      *result_size = 2;   }   else   {      clear_result_ready();      clear_param_reg();      write_params(params, num_params);      write_cmd(cmd);      get_result(result_buffer, result_size);   }   if (   ((result_buffer[0] & 0xf0) == 0x20)       && (num_retries < MAX_CDU31A_RETRIES))   {      num_retries++;      current->state = TASK_INTERRUPTIBLE;      schedule_timeout(HZ/10);  /* Wait .1 seconds on retries */      goto retry_cd_operation;   }   if (!recursive_call)   {      has_cd_task = NULL;      sony_inuse = 0;      wake_up_interruptible(&sony_wait);   }   restore_flags(flags);}/* * Handle an attention from the drive.  This will return 1 if it found one * or 0 if not (if one is found, the caller might want to call again). * * This routine counts the number of consecutive times it is called * (since this is always called from a while loop until it returns * a 0), and returns a 0 if it happens too many times.  This will help * prevent a lockup. */static inthandle_sony_cd_attention(void){   unsigned char atten_code;   static int num_consecutive_attentions = 0;   volatile int val;#if 0*DEBUG   printk("Entering handle_sony_cd_attention\n");#endif   if (is_attention())   {      if (num_consecutive_attentions > CDU31A_MAX_CONSECUTIVE_ATTENTIONS)      {         printk("cdu31a: Too many consecutive attentions: %d\n",                num_consecutive_attentions);         num_consecutive_attentions = 0;#if DEBUG         printk("Leaving handle_sony_cd_attention at %d\n", __LINE__);#endif         return(0);      }      clear_attention();      atten_code = read_result_register();      switch (atten_code)      {       /* Someone changed the CD.  Mark it as changed */      case SONY_MECH_LOADED_ATTN:         disk_changed = 1;	 sony_toc_read = 0;         sony_audio_status = CDROM_AUDIO_NO_STATUS;         sony_blocks_left = 0;         break;      case SONY_SPIN_DOWN_COMPLETE_ATTN:         /* Mark the disk as spun down. */         sony_spun_up = 0;         break;      case SONY_AUDIO_PLAY_DONE_ATTN:         sony_audio_status = CDROM_AUDIO_COMPLETED;         read_subcode();         break;      case SONY_EJECT_PUSHED_ATTN:         if (is_auto_eject)         {            sony_audio_status = CDROM_AUDIO_INVALID;         }         break;      case SONY_LEAD_IN_ERR_ATTN:      case SONY_LEAD_OUT_ERR_ATTN:      case SONY_DATA_TRACK_ERR_ATTN:      case SONY_AUDIO_PLAYBACK_ERR_ATTN:         sony_audio_status = CDROM_AUDIO_ERROR;         break;      }      num_consecutive_attentions++;#if DEBUG      printk("Leaving handle_sony_cd_attention at %d\n", __LINE__);#endif      return(1);   }   else if (abort_read_started)   {      while (is_result_reg_not_empty())      {         val = read_result_register();      }      clear_data_ready();      clear_result_ready();      /* Clear out the data */      while (is_data_requested())      {         val = read_data_register();      }      abort_read_started = 0;#if DEBUG      printk("Leaving handle_sony_cd_attention at %d\n", __LINE__);#endif      return(1);   }   num_consecutive_attentions = 0;#if 0*DEBUG   printk("Leaving handle_sony_cd_attention at %d\n", __LINE__);#endif   return(0);}/* Convert from an integer 0-99 to BCD */static inline unsigned intint_to_bcd(unsigned int val){   int retval;   retval = (val / 10) << 4;   retval = retval | val % 10;   return(retval);}/* Convert from BCD to an integer from 0-99 */static unsigned intbcd_to_int(unsigned int bcd){   return((((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f));}/* * Convert a logical sector value (like the OS would want to use for * a block device) to an MSF format. */static voidlog_to_msf(unsigned int log, unsigned char *msf){   log = log + LOG_START_OFFSET;   msf[0] = int_to_bcd(log / 4500);   log = log % 4500;   msf[1] = int_to_bcd(log / 75);   msf[2] = int_to_bcd(log % 75);}/* * Convert an MSF format to a logical sector. */static unsigned intmsf_to_log(unsigned char *msf){   unsigned int log;   log = msf[2];   log += msf[1] * 75;   log += msf[0] * 4500;   log = log - LOG_START_OFFSET;   return log;}/* * Take in integer size value and put it into a buffer like * the drive would want to see a number-of-sector value. */static voidsize_to_buf(unsigned int size,            unsigned char *buf){   buf[0] = size / 65536;   size = size % 65536;   buf[1] = size / 256;   buf[2] = size % 256;}/* Starts a read operation. Returns 0 on success and 1 on failure.    The read operation used here allows multiple sequential sectors    to be read and status returned for each sector.  The driver will   read the output one at a time as the requests come and abort the   operation if the requested sector is not the next one from the   drive. */static intstart_request(unsigned int sector,              unsigned int nsect,              int          read_nsect_only){   unsigned char params[6];   unsigned int read_size;   unsigned int retry_count;#if DEBUG   printk("Entering start_request\n");#endif   log_to_msf(sector, params);   /* If requested, read exactly what was asked. */   if (read_nsect_only)   {      read_size = nsect;   }   /*    * If the full read-ahead would go beyond the end of the media, trim    * it back to read just till the end of the media.    */   else if ((sector + nsect) >= sony_toc.lead_out_start_lba)   {      read_size = sony_toc.lead_out_start_lba - sector;   }   /* Read the full readahead amount. */   else   {      read_size = CDU31A_READAHEAD / 4;   }   size_to_buf(read_size, &params[3]);   /*    * Clear any outstanding attentions and wait for the drive to    * complete any pending operations.    */   while (handle_sony_cd_attention())      ;   retry_count = jiffies + SONY_JIFFIES_TIMEOUT;   while (time_before(jiffies, retry_count) && (is_busy()))   {      sony_sleep();            while (handle_sony_cd_attention())         ;   }   if (is_busy())   {      printk("CDU31A: Timeout while waiting to issue command\n");#if DEBUG      printk("Leaving start_request at %d\n", __LINE__);#endif      return(1);   }   else   {      /* Issue the command */      clear_result_ready();      clear_param_reg();      write_params(params, 6);      write_cmd(SONY_READ_BLKERR_STAT_CMD);      sony_blocks_left = read_size * 4;      sony_next_block = sector * 4;      readahead_dataleft = 0;      readahead_bad = 0;#if DEBUG      printk("Leaving start_request at %d\n", __LINE__);#endif      return(0);   }#if DEBUG   printk("Leaving start_request at %d\n", __LINE__);#endif}/* Abort a pending read operation.  Clear all the drive status and   readahead variables. */static voidabort_read(void){   unsigned char result_reg[2];   int           result_size;   volatile int  val;   do_sony_cd_cmd(SONY_ABORT_CMD, NULL, 0, result_reg, &result_size);   if ((result_reg[0] & 0xf0) == 0x20)   {      printk("CDU31A: Error aborting read, %s error\n",             translate_error(             result_reg[1]));   }   while (is_result_reg_not_empty())   {      val = read_result_register();   }   clear_data_ready();   clear_result_ready();   /* Clear out the data */   while (is_data_requested())   {      val = read_data_register();   }   sony_blocks_left = 0;   readahead_dataleft = 0;   readahead_bad = 0;}/* Called when the timer times out.  This will abort the   pending read operation. */static voidhandle_abort_timeout(unsigned long data){   unsigned long flags;#if DEBUG   printk("Entering handle_abort_timeout\n");#endif   save_flags(flags);   cli();   /* If it is in use, ignore it. */   if (!sony_inuse)   {      /* We can't use abort_read(), because it will sleep         or schedule in the timer interrupt.  Just start         the operation, finish it on the next access to         the drive. */      clear_result_ready();      clear_param_reg();      write_cmd(SONY_ABORT_CMD);      sony_blocks_left = 0;      readahead_dataleft = 0;      readahead_bad = 0;      abort_read_started = 1;   }   restore_flags(flags);#if DEBUG   printk("Leaving handle_abort_timeout\n");#endif}/* Actually get data and status from the drive. */static voidinput_data(char         *buffer,           unsigned int bytesleft,           unsigned int nblocks,           unsigned int offset,           unsigned int skip){   int i;   volatile unsigned char val;#if DEBUG   printk("Entering input_data\n");#endif   /* If an XA disk on a CDU31A, skip the first 12 bytes of data from      the disk.  The real data is after that. */   if (sony_xa_mode)   {      for(i=0; i<CD_XA_HEAD; i++)      {         val = read_data_register();      }   }

⌨️ 快捷键说明

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