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

📄 cdu31a.c

📁 powerpc内核 mpc8241芯片 linux系统下cdrom驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
{   return((inb(sony_cd_fifost_reg) & SONY_PARAM_WRITE_RDY_BIT) != 0);}static inline intis_result_reg_not_empty(void){   return((inb(sony_cd_fifost_reg) & SONY_RES_REG_NOT_EMP_BIT) != 0);}static inline voidreset_drive(void){   curr_control_reg = 0;   readahead_dataleft = 0;   sony_toc_read = 0;   outb(SONY_DRIVE_RESET_BIT, sony_cd_control_reg);}/* * Uniform cdrom interface function * reset drive and return when it is ready */static int scd_reset(struct cdrom_device_info * cdi){  int retry_count;  reset_drive();  retry_count = jiffies + SONY_RESET_TIMEOUT;  while (time_before(jiffies, retry_count) && (!is_attention()))  {     sony_sleep();  }  return 0;}static inline voidclear_attention(void){   outb(curr_control_reg | SONY_ATTN_CLR_BIT, sony_cd_control_reg);}static inline voidclear_result_ready(void){   outb(curr_control_reg | SONY_RES_RDY_CLR_BIT, sony_cd_control_reg);}static inline voidclear_data_ready(void){   outb(curr_control_reg | SONY_DATA_RDY_CLR_BIT, sony_cd_control_reg);}static inline voidclear_param_reg(void){   outb(curr_control_reg | SONY_PARAM_CLR_BIT, sony_cd_control_reg);}static inline unsigned charread_status_register(void){   return(inb(sony_cd_status_reg));}static inline unsigned charread_result_register(void){   return(inb(sony_cd_result_reg));}static inline unsigned charread_data_register(void){   return(inb(sony_cd_read_reg));}static inline voidwrite_param(unsigned char param){   outb(param, sony_cd_param_reg);}static inline voidwrite_cmd(unsigned char cmd){   outb(curr_control_reg | SONY_RES_RDY_INT_EN_BIT, sony_cd_control_reg);   outb(cmd, sony_cd_cmd_reg);}static voidcdu31a_interrupt(int irq, void *dev_id, struct pt_regs *regs){   unsigned char val;   if (abort_read_started)   {      /* We might be waiting for an abort to finish.  Don't         disable interrupts yet, though, because we handle         this one here. */      /* Clear out the result registers. */      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 something was waiting, wake it up now. */      if (cdu31a_irq_wait != NULL)      {         disable_interrupts();         wake_up(&cdu31a_irq_wait);      }   }   else if (cdu31a_irq_wait != NULL)   {      disable_interrupts();      wake_up(&cdu31a_irq_wait);   }   else   {      disable_interrupts();      printk("CDU31A: Got an interrupt but nothing was waiting\n");   }}/* * give more verbose error messages */static unsigned char *translate_error( unsigned char err_code ){   static unsigned char errbuf[80];   switch (err_code) {     case 0x10: return "illegal command ";     case 0x11: return "illegal parameter ";     case 0x20: return "not loaded ";     case 0x21: return "no disc ";     case 0x22: return "not spinning ";     case 0x23: return "spinning ";     case 0x25: return "spindle servo ";     case 0x26: return "focus servo ";     case 0x29: return "eject mechanism ";     case 0x2a: return "audio playing ";     case 0x2c: return "emergency eject ";     case 0x30: return "focus ";     case 0x31: return "frame sync ";     case 0x32: return "subcode address ";     case 0x33: return "block sync ";     case 0x34: return "header address ";     case 0x40: return "illegal track read ";     case 0x41: return "mode 0 read ";     case 0x42: return "illegal mode read ";     case 0x43: return "illegal block size read ";     case 0x44: return "mode read ";     case 0x45: return "form read ";     case 0x46: return "leadout read ";     case 0x47: return "buffer overrun ";     case 0x53: return "unrecoverable CIRC ";     case 0x57: return "unrecoverable LECC ";     case 0x60: return "no TOC ";     case 0x61: return "invalid subcode data ";     case 0x63: return "focus on TOC read ";     case 0x64: return "frame sync on TOC read ";     case 0x65: return "TOC data ";     case 0x70: return "hardware failure ";     case 0x91: return "leadin ";     case 0x92: return "leadout ";     case 0x93: return "data track ";   }   sprintf(errbuf, "unknown 0x%02x ", err_code);   return errbuf;}/* * Set the drive parameters so the drive will auto-spin-up when a * disk is inserted. */static voidset_drive_params(int want_doublespeed){   unsigned char res_reg[12];   unsigned int res_size;   unsigned char params[3];   params[0] = SONY_SD_AUTO_SPIN_DOWN_TIME;   params[1] = 0x00; /* Never spin down the drive. */   do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,                  params,                  2,                  res_reg,                  &res_size);   if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))   {      printk("  Unable to set spin-down time: 0x%2.2x\n", res_reg[1]);   }   params[0] = SONY_SD_MECH_CONTROL;   params[1] = SONY_AUTO_SPIN_UP_BIT; /* Set auto spin up */   if (is_auto_eject) params[1] |= SONY_AUTO_EJECT_BIT;      if (is_double_speed && want_doublespeed)   {      params[1] |= SONY_DOUBLE_SPEED_BIT; /* Set the drive to double speed if                                              possible */   }   do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD,                  params,                  2,                  res_reg,                  &res_size);   if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))   {      printk("  Unable to set mechanical parameters: 0x%2.2x\n", res_reg[1]);   }}/* * Uniform cdrom interface function * select reading speed for data access */static int scd_select_speed(struct cdrom_device_info *cdi, int speed){  if (speed == 0)    sony_speed = 1;  else     sony_speed = speed - 1;  set_drive_params(sony_speed);  return 0;}/* * Uniform cdrom interface function * lock or unlock eject button */static int scd_lock_door(struct cdrom_device_info *cdi, int lock){   if (lock == 0 && sony_usage == 1)   {      /* Unlock the door, only if nobody is using the drive */      is_auto_eject = 1;   } else {      is_auto_eject = 0;   }   set_drive_params(sony_speed);   return 0;}/* * This code will reset the drive and attempt to restore sane parameters. */static voidrestart_on_error(void){   unsigned char res_reg[12];   unsigned int res_size;   unsigned int retry_count;   printk("cdu31a: Resetting drive on error\n");   reset_drive();   retry_count = jiffies + SONY_RESET_TIMEOUT;   while (time_before(jiffies, retry_count) && (!is_attention()))   {      sony_sleep();   }   set_drive_params(sony_speed);   do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);   if ((res_size < 2) || ((res_reg[0] & 0xf0) == 0x20))   {      printk("cdu31a: Unable to spin up drive: 0x%2.2x\n", res_reg[1]);   }   current->state = TASK_INTERRUPTIBLE;   schedule_timeout(2*HZ);   sony_get_toc();}/* * This routine writes data to the parameter register.  Since this should * happen fairly fast, it is polled with no OS waits between. */static intwrite_params(unsigned char *params,             int num_params){   unsigned int retry_count;   retry_count = SONY_READY_RETRIES;   while ((retry_count > 0) && (!is_param_write_rdy()))   {      retry_count--;   }   if (!is_param_write_rdy())   {      return -EIO;   }   while (num_params > 0)   {      write_param(*params);      params++;      num_params--;   }   return 0;}/* * The following reads data from the command result register.  It is a * fairly complex routine, all status info flows back through this * interface.  The algorithm is stolen directly from the flowcharts in * the drive manual. */static voidget_result(unsigned char *result_buffer,           unsigned int *result_size){   unsigned char a, b;   int i;   unsigned int retry_count;   while (handle_sony_cd_attention())      ;   /* Wait for the result data to be ready */   retry_count = jiffies + SONY_JIFFIES_TIMEOUT;   while (time_before(jiffies, retry_count) && (is_busy() || (!(is_result_ready()))))   {      sony_sleep();      while (handle_sony_cd_attention())         ;   }   if (is_busy() || (!(is_result_ready())))   {#if DEBUG      printk("CDU31A timeout out %d\n", __LINE__);#endif      result_buffer[0] = 0x20;      result_buffer[1] = SONY_TIMEOUT_OP_ERR;      *result_size = 2;      return;   }   /*    * Get the first two bytes.  This determines what else needs    * to be done.    */   clear_result_ready();   a = read_result_register();   *result_buffer = a;   result_buffer++;   /* Check for block error status result. */   if ((a & 0xf0) == 0x50)   {      *result_size = 1;      return;   }   b = read_result_register();   *result_buffer = b;   result_buffer++;   *result_size = 2;   /*    * 0x20 means an error occurred.  Byte 2 will have the error code.    * Otherwise, the command succeeded, byte 2 will have the count of    * how many more status bytes are coming.    *    * The result register can be read 10 bytes at a time, a wait for    * result ready to be asserted must be done between every 10 bytes.    */   if ((a & 0xf0) != 0x20)   {      if (b > 8)      {         for (i=0; i<8; i++)         {            *result_buffer = read_result_register();            result_buffer++;            (*result_size)++;         }         b = b - 8;         while (b > 10)         {            retry_count = SONY_READY_RETRIES;            while ((retry_count > 0) && (!is_result_ready()))            {               retry_count--;            }            if (!is_result_ready())            {#if DEBUG               printk("CDU31A timeout out %d\n", __LINE__);#endif               result_buffer[0] = 0x20;               result_buffer[1] = SONY_TIMEOUT_OP_ERR;               *result_size = 2;               return;            }            clear_result_ready();                                            for (i=0; i<10; i++)            {               *result_buffer = read_result_register();               result_buffer++;               (*result_size)++;            }            b = b - 10;         }         if (b > 0)         {            retry_count = SONY_READY_RETRIES;            while ((retry_count > 0) && (!is_result_ready()))            {               retry_count--;            }            if (!is_result_ready())            {#if DEBUG               printk("CDU31A timeout out %d\n", __LINE__);#endif               result_buffer[0] = 0x20;               result_buffer[1] = SONY_TIMEOUT_OP_ERR;               *result_size = 2;               return;            }         }      }      while (b > 0)      {

⌨️ 快捷键说明

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