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

📄 mcd.c

📁 MINIX2.0操作系统源码 MINIX2.0操作系统源码
💻 C
📖 第 1 页 / 共 3 页
字号:

  /* Stop playing */
  if ((err = mcd_send_command(MCD_STOP_AUDIO)) != OK) return err;

  /* Keep in mind were we have to start again */
  PlayMss.begin_mss[MINUTES] = qc.position_mss[MINUTES];
  PlayMss.begin_mss[SECONDS] = qc.position_mss[SECONDS];
  PlayMss.begin_mss[SECTOR] = qc.position_mss[SECTOR];

  /* Update McdStatus */
  McdStatus |= AUDIO_PAUSED;

#if MCD_DEBUG >= 1
  printf("Mcd_paused at: %02d:%02d.%02d\n",
      PlayMss.begin_mss[MINUTES],
      PlayMss.begin_mss[SECONDS],
      PlayMss.begin_mss[SECTOR]);
#endif

  return OK;
} 


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

  /* we can only resume if we are in a pause state */
  if (!(McdStatus & AUDIO_PAUSED)) return EINVAL;

  /* start playing where we left off */
  if ((err = mcd_play_mss(PlayMss)) != OK) return err;

  McdStatus &= ~(AUDIO_PAUSED);

#if MCD_DEBUG >= 1
  printf("Mcd resumed at: %02d:%02d.%02d\n",
      PlayMss.begin_mss[MINUTES],
      PlayMss.begin_mss[SECONDS],
      PlayMss.begin_mss[SECTOR]);
#endif

  return OK;
} 


/*=========================================================================*
 *				ioctl_read_sub	 			   *	
 *=========================================================================*/
PRIVATE int ioctl_read_sub(m_ptr)
message *m_ptr;
{
  phys_bytes user_phys;
  struct cd_toc_entry sub;
  int err;

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

  /* Read the sub channel */
  if ((err = mcd_read_q_channel(&sub)) != OK) return err;

  /* Copy info to user */
  user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(sub));
  if (user_phys == 0) return(EFAULT);
  phys_copy(vir2phys(&sub), user_phys, (phys_bytes) sizeof(sub));

  return OK;
}  



/*=========================================================================*
 *				ioctl_read_toc	 			   *	
 *=========================================================================*/
PRIVATE int ioctl_read_toc(m_ptr)
message *m_ptr;
{
  phys_bytes user_phys;
  int err, toc_size;

  /* Try to read the table of contents */
  if ((err = mcd_read_toc()) != OK) return err;

  /* Get size of toc */
  toc_size = (DiskInfo.last_track + 1) * sizeof(struct cd_toc_entry);

  /* Copy to user */
  user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, toc_size);
  if (user_phys == 0) return(EFAULT);
  phys_copy(vir2phys(&Toc), user_phys, (phys_bytes) toc_size);

  return OK;
}  


/*=========================================================================*
 *				ioctl_disk_info	 			   *	
 *=========================================================================*/
PRIVATE int ioctl_disk_info(m_ptr)
message *m_ptr;
{
  phys_bytes user_phys;
  int err;

  /* Try to read the toc header */
  if ((err = mcd_get_disk_info()) != OK) return err;

  /* Copy info to user */
  user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(DiskInfo));
  if (user_phys == 0) return(EFAULT);
  phys_copy(vir2phys(&DiskInfo), user_phys, (phys_bytes) sizeof(DiskInfo));

  return OK;
}


/*=========================================================================*
 *				ioctl_play_mss	  			   *	
 *=========================================================================*/
PRIVATE int ioctl_play_mss(m_ptr)
message *m_ptr;
{
  phys_bytes user_phys;
  struct cd_play_mss mss;

  /* Get user data */
  user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(mss));
  if (user_phys == 0) return(EFAULT);
  phys_copy(user_phys, vir2phys(&mss), (phys_bytes) sizeof(mss));

  /* Try to play */
  return mcd_play_mss(mss);
}


/*=========================================================================*
 *				ioctl_play_ti	  			   *	
 *=========================================================================*/
PRIVATE int ioctl_play_ti(m_ptr)
message *m_ptr;
{
  phys_bytes user_phys;
  struct cd_play_track tracks;

  /* Get user data */
  user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS, sizeof(tracks));
  if (user_phys == 0) return(EFAULT);
  phys_copy(user_phys, vir2phys(&tracks), (phys_bytes) sizeof(tracks));

  /* Try to play */
  return mcd_play_tracks(tracks);
}


/*===========================================================================*
 *				mcd_prepare				     *
 *===========================================================================*/
PRIVATE struct device *mcd_prepare(device)
int device;
{
  /* Nothing to transfer as yet. */
  mcd_count = 0;

  /* Select partition. */
  if (device < DEV_PER_DRIVE) {			/* cd0, cd1, ... */
    mcd_dv = &mcd_part[device];
  } else
  if ((unsigned) (device -= MINOR_hd1a) < SUB_PER_DRIVE) { /* cd1a, cd1b, ... */
    mcd_dv = &mcd_subpart[device];
  } else {
    return NIL_DEV;
  }

  return mcd_dv;
}


/*===========================================================================*
 *				mcd_schedule				     *
 *===========================================================================*/
PRIVATE int mcd_schedule(proc_nr, iop)
int proc_nr;			/* process doing the request */
struct iorequest_s *iop;	/* pointer to read or write request */
{
/* Gather I/O requests on consecutive blocks so they may be read/written
 * in one controller command.  (There is enough time to compute the next
 * consecutive request while an unwanted block passes by.)
 */
  int r, opcode;
  unsigned long pos;
  unsigned nbytes;
  phys_bytes user_phys;

  /* This many bytes to read */
  nbytes = iop->io_nbytes;

  /* From/to this position on the device */
  pos = iop->io_position;

  /* To/from this user address */
  user_phys = numap(proc_nr, (vir_bytes) iop->io_buf, nbytes);
  if (user_phys == 0) return(iop->io_nbytes = EINVAL);

  /* Read or write? */
  opcode = iop->io_request & ~OPTIONAL_IO;

  /* Only read permitted on cdrom */
  if (opcode != DEV_READ) return EIO;

  /* What position on disk and how close to EOF? */
  if (pos >= mcd_dv->dv_size) return(OK);	/* At EOF */
  if (pos + nbytes > mcd_dv->dv_size) nbytes = mcd_dv->dv_size - pos;
  pos += mcd_dv->dv_base;

  if (mcd_count > 0 && pos != mcd_nextpos) {
	/* This new request can't be chained to the job being built */
	if ((r = mcd_finish()) != OK) return(r);
  }

  /* Next consecutive position. */
  mcd_nextpos = pos + nbytes;

  if (mcd_count == 0) 
  {
    /* The first request in a row, initialize. */
    mcd_tp = mcd_trans;
  }

  /* Store I/O parameters */
  mcd_tp->tr_iop = iop;
  mcd_tp->tr_pos = pos;
  mcd_tp->tr_count = nbytes;
  mcd_tp->tr_phys = user_phys;

  /* Update counters */
  mcd_tp++;
  mcd_count += nbytes;
  return(OK);
}


/*===========================================================================*
 *				mcd_finish				     *
 *===========================================================================*/
PRIVATE int mcd_finish()
{
/* Carry out the I/O requests gathered in mcd_trans[]. */

  struct trans *tp = mcd_trans;
  int err, errors;
  u8_t mss[3];
  unsigned long pos;
  unsigned count, n;

  if (mcd_count == 0) return(OK);	/* we're already done */

  /* Update status */
  mcd_get_status(1);
  if (McdStatus & (AUDIO_DISK | NO_DISK))
    return(tp->tr_iop->io_nbytes = EIO);
                                                          
  /* Set cooked mode */
  if ((err = mcd_set_mode(MCD_COOKED)) != OK)
    return(tp->tr_iop->io_nbytes = err);

  while (mcd_count > 0)
  {
    /* Position on the CD rounded down to the CD block size */
    pos = tp->tr_pos & ~MCD_BLOCK_MASK;

    /* Byte count rounded up. */
    count = (pos - tp->tr_pos) + mcd_count;
    count = (count + MCD_BLOCK_SIZE - 1) & ~MCD_BLOCK_MASK;

    /* XXX transfer size limits? */
    if (count > MCD_BLOCK_SIZE) count = MCD_BLOCK_SIZE;

    /* Compute disk position in min:sec:sector */
    block2mss(pos >> MCD_BLOCK_SHIFT, mss);

    /* Now try to read a block */
    errors = 0;
    while (errors < MCD_RETRIES) 
    {
      lock();
      out_byte(MCD_DATA_PORT, MCD_READ_FROM_TO);
      out_byte(MCD_DATA_PORT, bin2bcd(mss[MINUTES])); 
      out_byte(MCD_DATA_PORT, bin2bcd(mss[SECONDS])); 
      out_byte(MCD_DATA_PORT, bin2bcd(mss[SECTOR])); 
      out_byte(MCD_DATA_PORT, 0); 
      out_byte(MCD_DATA_PORT, 0); 
      out_byte(MCD_DATA_PORT, 1); 	/* XXX count in mss form? */
      unlock();

      /* Wait for data */
      if (mcd_data_ready(REPLY_DELAY) == OK) break;
      printf("Mcd: data time out\n");
      errors++;
    }
    if (errors == MCD_RETRIES) return(tp->tr_iop->io_nbytes = EIO);

    /* Prepare reading data. */
    out_byte(MCD_CONTROL_PORT, 0x04);

    while (pos < tp->tr_pos)
    {
      /* Discard bytes before the position we are really interested in. */
      n = tp->tr_pos - pos;
      if (n > DMA_BUF_SIZE) n = DMA_BUF_SIZE;
      port_read_byte(MCD_DATA_PORT, tmp_phys, n);
#if XXX
printf("count = %u, n = %u, tr_pos = %lu, io_nbytes = %u, tr_count = %u, mcd_count = %u\n",
count, n, 0, 0, 0, mcd_count);
#endif
      pos += n;
      count -= n;
    }

    while (mcd_count > 0 && count > 0)
    {
      /* Transfer bytes into the user buffers. */
      n = tp->tr_count;
      if (n > count) n = count;
      port_read_byte(MCD_DATA_PORT, tp->tr_phys, n);
#if XXX
printf("count = %u, n = %u, tr_pos = %lu, io_nbytes = %u, tr_count = %u, mcd_count = %u\n",
count, n, tp->tr_pos, tp->tr_iop->io_nbytes, tp->tr_count, mcd_count);
#endif
      tp->tr_phys += n;
      tp->tr_pos += n;
      tp->tr_iop->io_nbytes -= n;
      if ((tp->tr_count -= n) == 0) tp++;
      count -= n;
      mcd_count -= n;
    }

    while (count > 0)
    {
      /* Discard excess bytes. */
      n = count;
      if (n > DMA_BUF_SIZE) n = DMA_BUF_SIZE;
      port_read_byte(MCD_DATA_PORT, tmp_phys, n);
#if XXX
printf("count = %u, n = %u, tr_pos = %lu, io_nbytes = %u, tr_count = %u, mcd_count = %u\n",
count, n, 0, 0, 0, mcd_count);
#endif
      count -= n;
    }

    /* Finish reading data. */
    out_byte(MCD_CONTROL_PORT, 0x0c);
#if 0 /*XXX*/
    mcd_get_status(1);
    if (!(McdStatus & DISK_ERROR)) done = 1; /* OK, no errors */
#endif
  }
 
  return OK; 
}


/*============================================================================*
 *				mcd_geometry				      *
 *============================================================================*/
PRIVATE void mcd_geometry(entry)
struct partition *entry;		
{
/* The geometry of a cdrom doesn't look like the geometry of a regular disk,
 * so we invent a geometry to keep external programs happy.
 */ 
  entry->cylinders = (mcd_part[0].dv_size >> SECTOR_SHIFT) / (64 * 32);
  entry->heads = 64;
  entry->sectors = 32;
}


/*============================================================================*
 *				misc functions				      *
 *============================================================================*/
PRIVATE u8_t bin2bcd(u8_t b)
{
  /* Convert a number to binary-coded-decimal */
  int u,t;

  u = b%10;
  t = b/10;
  return (u8_t)(u | (t << 4));
}


PRIVATE void bcd2bin(u8_t *bcd)
{
  /* Convert binary-coded-decimal to binary :-) */

  *bcd = (*bcd >> 4) * 10 + (*bcd & 0xf);
}


PRIVATE void block2mss(block, mss)
long block;
u8_t *mss;
{
  /* Compute disk position of a block in min:sec:sector */

  block += MCD_SKIP;
  mss[MINUTES] = block/(SECONDS_PER_MINUTE * SECTORS_PER_SECOND);
  block %= (SECONDS_PER_MINUTE * SECTORS_PER_SECOND);
  mss[SECONDS] = block/(SECTORS_PER_SECOND);
  mss[SECTOR] = block%(SECTORS_PER_SECOND);
}


PRIVATE long mss2block(u8_t *mss)
{
  /* Compute block number belonging to 
   * disk position min:sec:sector 
   */

  return ((((unsigned long) mss[MINUTES] * SECONDS_PER_MINUTE
	+ (unsigned long) mss[SECONDS]) * SECTORS_PER_SECOND)
	+ (unsigned long) mss[SECTOR]) - MCD_SKIP;
}
#endif /* ENABLE_MITSUMI_CDROM */

⌨️ 快捷键说明

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