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

📄 cdu31a.c

📁 LINUX1.0内核源代码,学习LINUX编程的一定要看。
💻 C
📖 第 1 页 / 共 4 页
字号:
      final_pos_msf[0] = params[4];      final_pos_msf[1] = params[5];      final_pos_msf[2] = params[6];      sony_audio_status = CDROM_AUDIO_PLAY;      return 0;      break;   case CDROMREADTOCHDR:        /* Read the table of contents header */      {         struct cdrom_tochdr *hdr;         struct cdrom_tochdr loc_hdr;                  sony_get_toc();         if (!sony_toc_read)         {            return -EIO;         }                  hdr = (struct cdrom_tochdr *) arg;         verify_area(VERIFY_WRITE, hdr, sizeof(*hdr));         loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);         loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);         memcpy_tofs(hdr, &loc_hdr, sizeof(*hdr));      }      return 0;      break;   case CDROMREADTOCENTRY:      /* Read a given table of contents entry */      {         struct cdrom_tocentry *entry;         struct cdrom_tocentry loc_entry;         int track_idx;         unsigned char *msf_val = NULL;                  sony_get_toc();         if (!sony_toc_read)         {            return -EIO;         }                  entry = (struct cdrom_tocentry *) arg;         verify_area(VERIFY_READ, entry, sizeof(*entry));         verify_area(VERIFY_WRITE, entry, sizeof(*entry));                  memcpy_fromfs(&loc_entry, entry, sizeof(loc_entry));                  /* Lead out is handled separately since it is special. */         if (loc_entry.cdte_track == CDROM_LEADOUT)         {            loc_entry.cdte_adr = sony_toc->address2;            loc_entry.cdte_ctrl = sony_toc->control2;            msf_val = sony_toc->lead_out_start_msf;         }         else         {            track_idx = find_track(int_to_bcd(loc_entry.cdte_track));            if (track_idx < 0)            {               return -EINVAL;            }                        loc_entry.cdte_adr = sony_toc->tracks[track_idx].address;            loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;            msf_val = sony_toc->tracks[track_idx].track_start_msf;         }                  /* Logical buffer address or MSF format requested? */         if (loc_entry.cdte_format == CDROM_LBA)         {            loc_entry.cdte_addr.lba = msf_to_log(msf_val);         }         else if (loc_entry.cdte_format == CDROM_MSF)         {            loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);            loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val+1));            loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val+2));         }         memcpy_tofs(entry, &loc_entry, sizeof(*entry));      }      return 0;      break;   case CDROMPLAYTRKIND:     /* Play a track.  This currently ignores index. */      {         struct cdrom_ti ti;         int track_idx;                  sony_get_toc();         if (!sony_toc_read)         {            return -EIO;         }                  verify_area(VERIFY_READ, (char *) arg, sizeof(ti));                  memcpy_fromfs(&ti, (char *) arg, sizeof(ti));         if (   (ti.cdti_trk0 < sony_toc->first_track_num)             || (ti.cdti_trk0 > sony_toc->last_track_num)             || (ti.cdti_trk1 < ti.cdti_trk0))         {            return -EINVAL;         }                  track_idx = find_track(int_to_bcd(ti.cdti_trk0));         if (track_idx < 0)         {            return -EINVAL;         }         params[1] = sony_toc->tracks[track_idx].track_start_msf[0];         params[2] = sony_toc->tracks[track_idx].track_start_msf[1];         params[3] = sony_toc->tracks[track_idx].track_start_msf[2];                  /*          * If we want to stop after the last track, use the lead-out          * MSF to do that.          */         if (ti.cdti_trk1 >= bcd_to_int(sony_toc->last_track_num))         {            log_to_msf(msf_to_log(sony_toc->lead_out_start_msf)-1,                       &(params[4]));         }         else         {            track_idx = find_track(int_to_bcd(ti.cdti_trk1+1));            if (track_idx < 0)            {               return -EINVAL;            }            log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf)-1,                       &(params[4]));         }         params[0] = 0x03;                  do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);                  do_sony_cd_cmd(SONY_AUDIO_PLAYBACK_CMD, params, 7, res_reg, &res_size);         if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))         {            printk("Params: %x %x %x %x %x %x %x\n", params[0], params[1],                   params[2], params[3], params[4], params[5], params[6]);            printk("Sony CDROM error 0x%2.2x (CDROMPLAYTRKIND\n", res_reg[1]);            return -EIO;         }                  /* Save the final position for pauses and resumes */         final_pos_msf[0] = params[4];         final_pos_msf[1] = params[5];         final_pos_msf[2] = params[6];         sony_audio_status = CDROM_AUDIO_PLAY;         return 0;      }        case CDROMSUBCHNL:   /* Get subchannel info */      return sony_get_subchnl_info(arg);   case CDROMVOLCTRL:   /* Volume control.  What volume does this change, anyway? */      {         struct cdrom_volctrl volctrl;                  verify_area(VERIFY_READ, (char *) arg, sizeof(volctrl));                  memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));         params[0] = SONY_SD_AUDIO_VOLUME;         params[1] = volctrl.channel0;         params[2] = volctrl.channel1;         do_sony_cd_cmd(SONY_SET_DRIVE_PARAM_CMD, params, 3, res_reg, &res_size);         if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))         {            printk("Sony CDROM error 0x%2.2x (CDROMVOLCTRL)\n", res_reg[1]);            return -EIO;         }      }      return 0;   case CDROMEJECT:     /* Eject the drive */      do_sony_cd_cmd(SONY_AUDIO_STOP_CMD, NULL, 0, res_reg, &res_size);      do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);      sony_audio_status = CDROM_AUDIO_INVALID;      do_sony_cd_cmd(SONY_EJECT_CMD, NULL, 0, res_reg, &res_size);      if ((res_size < 2) || ((res_reg[0] & 0x20) == 0x20))      {         printk("Sony CDROM error 0x%2.2x (CDROMEJECT)\n", res_reg[1]);         return -EIO;      }      return 0;      break;        default:      return -EINVAL;   }}/* * Open the drive for operations.  Spin the drive up and read the table of * contents if these have not already been done. */static intscd_open(struct inode *inode,         struct file *filp){   unsigned char res_reg[2];   unsigned int res_size;   int num_spin_ups;   if (!sony_spun_up)   {      num_spin_ups = 0;respinup_on_open:      do_sony_cd_cmd(SONY_SPIN_UP_CMD, NULL, 0, res_reg, &res_size);      /* The drive sometimes returns error 0.  I don't know why, but ignore         it.  It seems to mean the drive has already done the operation. */      if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0)))      {         printk("Sony CDROM error 0x%2.2x (scd_open, spin up)\n", res_reg[1]);         return -EIO;      }            do_sony_cd_cmd(SONY_READ_TOC_CMD, NULL, 0, res_reg, &res_size);      /* The drive sometimes returns error 0.  I don't know why, but ignore         it.  It seems to mean the drive has already done the operation. */      if ((res_size < 2) || ((res_reg[0] != 0) && (res_reg[1] != 0)))      {         /* If the drive is already playing, its ok.  */         if ((res_reg[1] == SONY_AUDIO_PLAYING_ERR) || (res_reg[1] == 0))         {            goto drive_spinning;         }         /* If the drive says it is not spun up (even though we just did it!)            then retry the operation at least a few times. */         if (   (res_reg[1] == SONY_NOT_SPIN_ERR)             && (num_spin_ups < MAX_CDU31A_RETRIES))         {            num_spin_ups++;            goto respinup_on_open;         }         printk("Sony CDROM error 0x%2.2x (scd_open, read toc)\n", res_reg[1]);         do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);                  return -EIO;      }      sony_get_toc();      if (!sony_toc_read)      {         do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);         return -EIO;      }      sony_spun_up = 1;   }drive_spinning:   if (inode)   {      check_disk_change(inode->i_rdev);   }   sony_usage++;   return 0;}/* * Close the drive.  Spin it down if no task is using it.  The spin * down will fail if playing audio, so audio play is OK. */static voidscd_release(struct inode *inode,         struct file *filp){   unsigned char res_reg[2];   unsigned int  res_size;   if (sony_usage > 0)   {      sony_usage--;   }   if (sony_usage == 0)   {      sync_dev(inode->i_rdev);      do_sony_cd_cmd(SONY_SPIN_DOWN_CMD, NULL, 0, res_reg, &res_size);      sony_spun_up = 0;   }}static struct file_operations scd_fops = {   NULL,                   /* lseek - default */   block_read,             /* read - general block-dev read */   block_write,            /* write - general block-dev write */   NULL,                   /* readdir - bad */   NULL,                   /* select */   scd_ioctl,              /* ioctl */   NULL,                   /* mmap */   scd_open,               /* open */   scd_release,            /* release */   NULL                    /* fsync */};/* The different types of disc loading mechanisms supported */static char *load_mech[] = { "caddy", "tray", "pop-up", "unknown" };/* Read-ahead buffer sizes for different drives.  These are just arbitrary   values, I don't know what is really optimum. */static unsigned int mem_size[] = { 16384, 16384, 16384, 2048 };voidget_drive_configuration(unsigned short base_io,                        unsigned char res_reg[],                        unsigned int *res_size){   int retry_count;   /* Set the base address */   sony_cd_base_io = base_io;   /* Set up all the register locations */   sony_cd_cmd_reg = sony_cd_base_io + SONY_CMD_REG_OFFSET;   sony_cd_param_reg = sony_cd_base_io + SONY_PARAM_REG_OFFSET;   sony_cd_write_reg = sony_cd_base_io + SONY_WRITE_REG_OFFSET;   sony_cd_control_reg = sony_cd_base_io + SONY_CONTROL_REG_OFFSET;   sony_cd_status_reg = sony_cd_base_io + SONY_STATUS_REG_OFFSET;   sony_cd_result_reg = sony_cd_base_io + SONY_RESULT_REG_OFFSET;   sony_cd_read_reg = sony_cd_base_io + SONY_READ_REG_OFFSET;   sony_cd_fifost_reg = sony_cd_base_io + SONY_FIFOST_REG_OFFSET;   /*    * Check to see if anything exists at the status register location.    * I don't know if this is a good way to check, but it seems to work    * ok for me.    */   if (read_status_register() != 0xff)   {      /*       * Reset the drive and wait for attention from it (to say its reset).       * If you don't wait, the next operation will probably fail.       */      reset_drive();      retry_count = jiffies + SONY_RESET_TIMEOUT;      while ((retry_count > jiffies) && (!is_attention()))      {         sony_sleep();      }      /* If attention is never seen probably not a CDU31a present */      if (!is_attention())      {         res_reg[0] = 0x20;         return;      }      /*       * Get the drive configuration.       */      do_sony_cd_cmd(SONY_REQ_DRIVE_CONFIG_CMD,                     NULL,                     0,                     (unsigned char *) res_reg,                     res_size);      return;   }   /* Return an error */   res_reg[0] = 0x20;}/* * Initialize the driver. */unsigned longcdu31a_init(unsigned long mem_start, unsigned long mem_end){   struct s_sony_drive_config drive_config;   unsigned int res_size;   int i;   int drive_found;   /*    * According to Alex Freed (freed@europa.orion.adobe.com), this is    * required for the Fusion CD-16 package.  If the sound driver is    * loaded, it should work fine, but just in case...    *    * The following turn on the CD-ROM interface for a Fusion CD-16.    */   outb(0xbc, 0x9a01);   outb(0xe2, 0x9a01);   i = 0;   drive_found = 0;   while (   (cdu31a_addresses[i] != 0)          && (!drive_found))   {      if (check_region(cdu31a_addresses[i], 4)) {	  i++;	  continue;      }      get_drive_configuration(cdu31a_addresses[i],                               drive_config.exec_status,                               &res_size);      if ((res_size > 2) && ((drive_config.exec_status[0] & 0x20) == 0x00))      {         drive_found = 1;	 snarf_region(cdu31a_addresses[i], 4);         if (register_blkdev(MAJOR_NR,"cdu31a",&scd_fops))         {            printk("Unable to get major %d for CDU-31a\n", MAJOR_NR);            return mem_start;         }         sony_buffer_size = mem_size[SONY_HWC_GET_BUF_MEM_SIZE(drive_config)];         sony_buffer_sectors = sony_buffer_size / 2048;         printk("Sony I/F CDROM : %8.8s %16.16s %8.8s with %s load mechanism\n",                drive_config.vendor_id,                drive_config.product_id,                drive_config.product_rev_level,                load_mech[SONY_HWC_GET_LOAD_MECH(drive_config)]);         printk("  using %d byte buffer", sony_buffer_size);         if (SONY_HWC_AUDIO_PLAYBACK(drive_config))         {            printk(", capable of audio playback");         }         printk("\n");         set_drive_params();         blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;         read_ahead[MAJOR_NR] = 8;               /* 8 sector (4kB) read-ahead */         sony_toc = (struct s_sony_toc *) mem_start;         mem_start += sizeof(*sony_toc);         last_sony_subcode = (struct s_sony_subcode *) mem_start;         mem_start += sizeof(*last_sony_subcode);         sony_buffer = (unsigned char *) mem_start;         mem_start += sony_buffer_size;      }      i++;   }      return mem_start;}

⌨️ 快捷键说明

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