📄 mcd.c
字号:
/* 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 + -