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

📄 mcd.c

📁 MINIX2.0操作系统源码 MINIX2.0操作系统源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (mcd_get_status(0) != -1 &&
         !(McdStatus & DISK_ERROR)) break; 
  }
  if (i == MCD_RETRIES) return EIO;        /* Operation failed */

  return OK; /* Operation succeeded */
}


/*=========================================================================*
 *				mcd_send_command   			   *	
 *=========================================================================*/
PRIVATE int mcd_send_command(command)
int command;  	/* command to send */
{
  int i;

  for (i = 0; i < MCD_RETRIES; i++)
  {
    out_byte(MCD_DATA_PORT, command);      /* send command */
    if (mcd_get_status(0) != -1 && 
         !(McdStatus & DISK_ERROR)) break; 
  }
  if (i == MCD_RETRIES) return EIO;        /* operation failed */

  return OK;
}


/*=========================================================================*
 *				mcd_init				   *	
 *=========================================================================*/
PRIVATE int mcd_init()
{
  /* Initialize the drive and get the version bytes, this is done only
     once when the system gets up. We can't use mcd_ready because
     the clock task is not available yet.
   */

  u8_t version[3];
  int i;
  u32_t n;
  struct milli_state ms;

  /* Reset the flag port and remove all pending data, if we do
   * not do this properly the drive won't cooperate.
   */
  out_byte(MCD_FLAG_PORT, 0x00); 	
  for (n = 0; n < 1000000; n++)
    (void) in_byte(MCD_FLAG_PORT);

  /* Now see if the drive will report its status */
  if (mcd_get_status(1) == -1)
  {
    /* Too bad, drive will not listen */
    printf("%s: init failed, no Mitsumi cdrom present\n", mcd_name());
    return -1; 
  }

  /* Find out drive version */
  out_byte(MCD_DATA_PORT, MCD_GET_VERSION);
  milli_start(&ms);
  for (i = 0; i < 3; i++)
  {
    while (in_byte(MCD_FLAG_PORT) & MCD_BUSY)
    {
      if (milli_elapsed(&ms) >= 1000) 
      {
	printf("%s: can't get version of Mitsumi cdrom\n", mcd_name());
	return -1;
      }
    }
    version[i] = in_byte(MCD_DATA_PORT);
  }
 
  if (version[1] == 'D')
    printf("%s: Mitsumi FX001D CD-ROM\n", mcd_name());
  else 
    printf("%s: Mitsumi CD-ROM version %02x%02x%02x\n", mcd_name(), 
            version[0], version[1], version[2]);

  /* Newer drive models need this */
  if (version[1] >= 4) out_byte(MCD_CONTROL_PORT, MCD_PICKLE);

  /* Register interrupt vector and enable interrupt 
   * currently the interrupt is not used because
   * the controller isn't set up to do dma.  XXX
   */
  put_irq_handler(mcd_irq, c_handler);
  enable_irq(mcd_irq);

  mcd_avail = 1;
  return OK;
}


/*=========================================================================*
 *				c_handler 	  			   *	
 *=========================================================================*/
PRIVATE int c_handler(irq)
int irq; 	/* irq number */
{
  /* The interrupt handler, I never got an interrupt but its here just
   * in case...
   */

  /* Send interrupt message to cdrom task */
#if XXX
#if __minix_vmd
  interrupt(mcd_tasknr);
#else
  interrupt(CDROM);
#endif
#endif

  return 1;
}


/*=========================================================================*
 *				mcd_play_mss	  			   *	
 *=========================================================================*/
PRIVATE int mcd_play_mss(mss)
struct cd_play_mss mss;  /* from where to play minute:second.sector */
{
  /* Command the drive to start playing at min:sec.sector */

  int i;

#if MCD_DEBUG >= 1
  printf("Play_mss: begin: %02d:%02d.%02d  end: %02d:%02d.%02d\n",
          mss.begin_mss[MINUTES], mss.begin_mss[SECONDS],
          mss.begin_mss[SECTOR], mss.end_mss[MINUTES], 
          mss.end_mss[SECONDS], mss.end_mss[SECTOR]); 
#endif

  for (i=0; i < MCD_RETRIES; i++)     /* Try it more than once */
  {
    lock();        /* No interrupts when we issue this command */

    /* Send command with paramters to drive */
    out_byte(MCD_DATA_PORT, MCD_READ_FROM_TO);
    out_byte(MCD_DATA_PORT, bin2bcd(mss.begin_mss[MINUTES]));
    out_byte(MCD_DATA_PORT, bin2bcd(mss.begin_mss[SECONDS]));
    out_byte(MCD_DATA_PORT, bin2bcd(mss.begin_mss[SECTOR]));
    out_byte(MCD_DATA_PORT, bin2bcd(mss.end_mss[MINUTES]));
    out_byte(MCD_DATA_PORT, bin2bcd(mss.end_mss[SECONDS]));
    out_byte(MCD_DATA_PORT, bin2bcd(mss.end_mss[SECTOR]));

    unlock();	   /* Enable interrupts again */

    mcd_get_status(0);                    /* See if all went well */
    if (McdStatus & AUDIO_PLAYING) break; /* Ok, we're playing */
  }

  if (i == MCD_RETRIES) return EIO;       /* Command failed */

  /* keep in mind where we going in case of a future resume */
  PlayMss.end_mss[MINUTES] = mss.end_mss[MINUTES];
  PlayMss.end_mss[SECONDS] = mss.end_mss[SECONDS];
  PlayMss.end_mss[SECTOR] = mss.end_mss[SECTOR];

  McdStatus &= ~(AUDIO_PAUSED);

  return(OK);
}


/*=========================================================================*
 *				mcd_play_tracks	  			   *	
 *=========================================================================*/
PRIVATE int mcd_play_tracks(tracks)
struct cd_play_track tracks;     /* which tracks to play */
{
  /* Command the drive to play tracks */
  
  int i, err;
  struct cd_play_mss mss;

#if MCD_DEBUG >= 1
  printf("Play tracks: begin: %02d end: %02d\n",
           tracks.begin_track, tracks.end_track);
#endif

  /* First read the table of contents */
  if ((err = mcd_read_toc()) != OK) return err; 
 
  /* Check if parameters are valid */
  if (tracks.begin_track < DiskInfo.first_track ||
      tracks.end_track > DiskInfo.last_track ||
      tracks.begin_track > tracks.end_track)
    return EINVAL;


  /* Convert the track numbers to min:sec.sector */
  for (i=0; i<3; i++)
  {
    mss.begin_mss[i] = Toc[tracks.begin_track].position_mss[i]; 
    mss.end_mss[i] = Toc[tracks.end_track+1].position_mss[i]; 
  }

  return(mcd_play_mss(mss));     /* Start playing */
}


/*=========================================================================*
 *				mcd_get_disk_info			   *	
 *=========================================================================*/
PRIVATE int mcd_get_disk_info()
{
  /* Get disk info */

  int i, err;

  if (McdStatus & INFO_UPTODATE) return OK; /* No need to read info again */

  /* Issue the get volume info command */
  if ((err = mcd_send_command(MCD_GET_VOL_INFO)) != OK) return err;

  /* Fill global DiskInfo */
  for (i=0; i < sizeof(DiskInfo); i++) 
  {
    if ((err = mcd_get_reply((u8_t *)(&DiskInfo) + i, REPLY_DELAY)) !=OK)
      return err;
    bcd2bin((u8_t *)(&DiskInfo) + i);  
  }

#if MCD_DEBUG >= 1
  printf("Mitsumi disk info: first: %d last: %d first %02d:%02d.%02d length: %02d:%02d.%02d\n",
      DiskInfo.first_track,
      DiskInfo.last_track,
      DiskInfo.first_track_mss[MINUTES],
      DiskInfo.first_track_mss[SECONDS],
      DiskInfo.first_track_mss[SECTOR],
      DiskInfo.disk_length_mss[MINUTES],	
      DiskInfo.disk_length_mss[SECONDS],	
      DiskInfo.disk_length_mss[SECTOR]);	
#endif

  /* Update global status info */
  McdStatus |= INFO_UPTODATE; /* toc header has been read */
  McdStatus &= ~TOC_UPTODATE; /* toc has not been read yet */

  return OK;
}



/*=========================================================================*
 *				mcd_read_q_channel 			   *	
 *=========================================================================*/
PRIVATE int mcd_read_q_channel(qc)
struct cd_toc_entry *qc;  /* struct to return q-channel info in */
{
  /* Read the qchannel info, if we we're already playing this returns
   * the relative position and the absolute position of where we are
   * in min:sec.sector. If we're not playing, this returns an entry
   * from the table of contents
   */
 
  int i, err; 

  /* Issue the command */
  if ((err = mcd_send_command(MCD_GET_Q_CHANNEL)) != OK) return err;

  /* Read the info */
  for (i=0; i < sizeof(struct cd_toc_entry); i++)
  {
    /* Return error on timeout */
    if ((err = mcd_get_reply((u8_t *)qc + i, REPLY_DELAY)) != OK) 
      return err;

    bcd2bin((u8_t *)qc + i);  /* Convert value to binary */
  }
 
#if MCD_DEBUG >= 2
  printf("qchannel info: ctl_addr: %d track: %d index: %d length %02d:%02d.%02d pos: %02d:%02d.%02d\n",
      qc->control_address,
      qc->track_nr,
      qc->index_nr,
      qc->track_time_mss[MINUTES],	
      qc->track_time_mss[SECONDS],	
      qc->track_time_mss[SECTOR],
      qc->position_mss[MINUTES],	
      qc->position_mss[SECONDS],	
      qc->position_mss[SECTOR]);
#endif

  return OK;  /* All done */
}


/*=========================================================================*
 *				mcd_read_toc	 			   *	
 *=========================================================================*/
PRIVATE int mcd_read_toc()
{
  /* Read the table of contents (TOC) */

  struct cd_toc_entry q_info;
  int current_track, current_index;
  int err,i;


  if (McdStatus & TOC_UPTODATE) return OK; /* No need to read toc again */
	
  /* Clear toc table */
  for (i = 0; i < MAX_TRACKS; i++) Toc[i].index_nr = 0; 		

  /* Read disk info */
  if ((err = mcd_get_disk_info()) != OK) return err;

  /* Calculate track to start with */ 
  current_track = DiskInfo.last_track - DiskInfo.first_track + 1;

  /* Set read toc mode */
  if ((err = mcd_set_mode(MCD_TOC)) != OK) return err;

  /* Read the complete TOC, on every read-q-channel command we get a random
   * TOC entry depending on how far we are in the q-channel, collect entries
   * as long as we don't have the complete TOC. There's a limit of 600 here,
   * if we don't have the complete TOC after 600 reads we quit with an error
   */
  for (i = 0; (i < 600 && current_track > 0); i++)
  {
    /* Try to read a TOC entry */
    if ((err = mcd_read_q_channel(&q_info)) != OK) break;	

    /* Is this a valid track number and didn't we have it yet ? */
    current_index = q_info.index_nr;    
    if (current_index >= DiskInfo.first_track &&
        current_index <= DiskInfo.last_track &&
        q_info.track_nr == 0)
    {
      /* Copy entry into toc table */
      if (Toc[current_index].index_nr == 0)
      {
        Toc[current_index].control_address = q_info.control_address;
        Toc[current_index].track_nr = current_index;
        Toc[current_index].index_nr = 1;
        Toc[current_index].track_time_mss[MINUTES] = q_info.track_time_mss[MINUTES];
        Toc[current_index].track_time_mss[SECONDS] = q_info.track_time_mss[SECONDS];
        Toc[current_index].track_time_mss[SECTOR] = q_info.track_time_mss[SECTOR];
        Toc[current_index].position_mss[MINUTES] = q_info.position_mss[MINUTES];
        Toc[current_index].position_mss[SECONDS] = q_info.position_mss[SECONDS];
        Toc[current_index].position_mss[SECTOR] = q_info.position_mss[SECTOR];
        current_track--;
      }
    }
  }
  if (err) return err;	 /* Do we have all toc entries? */

  /* Fill in lead out */
  current_index = DiskInfo.last_track + 1;
  Toc[current_index].control_address = 
                                  Toc[current_index-1].control_address;
  Toc[current_index].track_nr = 0;
  Toc[current_index].index_nr = LEAD_OUT;
  Toc[current_index].position_mss[MINUTES] = DiskInfo.disk_length_mss[MINUTES];
  Toc[current_index].position_mss[SECONDS] = DiskInfo.disk_length_mss[SECONDS];
  Toc[current_index].position_mss[SECTOR] = DiskInfo.disk_length_mss[SECTOR];

  /* Return to cooked mode */
  if ((err = mcd_set_mode(MCD_COOKED)) != OK) return err; 

  /* Update global status */
  McdStatus |= TOC_UPTODATE;

#if MCD_DEBUG >= 1
  for (i = DiskInfo.first_track; i <= current_index; i++)
  {
    printf("Mitsumi toc %d: trk %d  index %d  time %02d:%02d.%02d  pos: %02d:%02d.%02d\n",
        i,
        Toc[i].track_nr,
        Toc[i].index_nr,
        Toc[i].track_time_mss[MINUTES],
        Toc[i].track_time_mss[SECONDS],
        Toc[i].track_time_mss[SECTOR],
        Toc[i].position_mss[MINUTES],
        Toc[i].position_mss[SECONDS],
        Toc[i].position_mss[SECTOR]);
  }
#endif

  return OK;
}


/*=========================================================================*
 *				mcd_stop	 			   *	
 *=========================================================================*/
PRIVATE int mcd_stop()
{
  int err;

  if ((err = mcd_send_command(MCD_STOP)) != OK ) return err;

  McdStatus &= ~(AUDIO_PAUSED);

  return OK;
} 


/*=========================================================================*
 *				mcd_eject	 			   *	
 *=========================================================================*/
PRIVATE int mcd_eject()
{
  int err;

  if ((err = mcd_send_command(MCD_EJECT)) != OK) return err;
  return OK;
} 


/*=========================================================================*
 *				mcd_pause	 			   *	
 *=========================================================================*/
PRIVATE int mcd_pause()
{
  int err;
  struct cd_toc_entry qc;

  /* We can only pause when we are playing audio */
  if (!(McdStatus & AUDIO_PLAYING)) return EINVAL;

  /* Look where we are */
  if ((err = mcd_read_q_channel(&qc)) != OK) return err;

⌨️ 快捷键说明

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