📄 sbpcd.c
字号:
return (i);
}
i=xx_ReadTocEntry(DS[d].n_first_track);
if (i<0)
{
DPRINTF((DBG_INF,"SBPCD: DiskInfo: xx_ReadTocEntry(1) returns %d\n", i));
return (i);
}
i=xx_ReadUPC();
if (i<0)
{
DPRINTF((DBG_INF,"SBPCD: DiskInfo: xx_ReadUPC returns %d\n", i));
return (i);
}
return (0);
}
/*==========================================================================*/
/*
* called always if driver gets entered
* returns 0 or ERROR2 or ERROR15
*/
static int prepare(u_char func, u_char subfunc)
{
int i;
if (!new_drive)
{
i=inb(CDi_status);
if (i&s_attention) GetStatus();
}
else GetStatus();
if (DS[d].CD_changed==0xFF)
{
#if MANY_SESSION
#else
DS[d].diskstate_flags=0;
#endif MANY_SESSION
DS[d].audio_state=0;
if (!st_diskok)
{
i=check_allowed1(func,subfunc);
if (i<0) return (-2);
}
else
{
i=check_allowed3(func,subfunc);
if (i<0)
{
DS[d].CD_changed=1;
return (-15);
}
}
}
else
{
if (!st_diskok)
{
#if MANY_SESSION
#else
DS[d].diskstate_flags=0;
#endif MANY_SESSION
DS[d].audio_state=0;
i=check_allowed1(func,subfunc);
if (i<0) return (-2);
}
else
{
if (st_busy)
{
if (DS[d].audio_state!=audio_pausing)
{
i=check_allowed2(func,subfunc);
if (i<0) return (-2);
}
}
else
{
if (DS[d].audio_state==audio_playing) seek_pos_audio_end();
DS[d].audio_state=0;
}
if (!frame_size_valid)
{
i=DiskInfo();
if (i<0)
{
#if MANY_SESSION
#else
DS[d].diskstate_flags=0;
#endif MANY_SESSION
DS[d].audio_state=0;
i=check_allowed1(func,subfunc);
if (i<0) return (-2);
}
}
}
}
return (0);
}
/*==========================================================================*/
static int xx_PlayAudioMSF(int pos_audio_start,int pos_audio_end)
{
int i;
if (DS[d].audio_state==audio_playing) return (-EINVAL);
clr_cmdbuf();
if (new_drive)
{
drvcmd[0]=0x0E;
flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus |
f_obey_p_check | f_wait_if_busy;
}
else
{
drvcmd[0]=0x0B;
flags_cmd_out = f_putcmd | f_respo2 | f_lopsta | f_getsta |
f_ResponseStatus | f_obey_p_check | f_wait_if_busy;
}
drvcmd[1]=(pos_audio_start>>16)&0x00FF;
drvcmd[2]=(pos_audio_start>>8)&0x00FF;
drvcmd[3]=pos_audio_start&0x00FF;
drvcmd[4]=(pos_audio_end>>16)&0x00FF;
drvcmd[5]=(pos_audio_end>>8)&0x00FF;
drvcmd[6]=pos_audio_end&0x00FF;
response_count=0;
i=cmd_out();
return (i);
}
/*==========================================================================*/
/*==========================================================================*/
/*==========================================================================*/
/*==========================================================================*/
/*
* ioctl support, adopted from scsi/sr_ioctl.c and mcd.c
*/
static int sbpcd_ioctl(struct inode *inode,struct file *file,
u_int cmd, u_long arg)
{
int i, st;
DPRINTF((DBG_IO2,"SBPCD: ioctl(%d, 0x%08lX, 0x%08lX)\n",
MINOR(inode->i_rdev), cmd, arg));
if (!inode) return (-EINVAL);
i=MINOR(inode->i_rdev);
if ( (i<0) || (i>=NR_SBPCD) )
{
printk("SBPCD: ioctl: bad device: %d\n", i);
return (-ENODEV); /* no such drive */
}
switch_drive(i);
st=GetStatus();
if (st<0) return (-EIO);
if (!toc_valid)
{
i=DiskInfo();
if (i<0) return (-EIO); /* error reading TOC */
}
DPRINTF((DBG_IO2,"SBPCD: ioctl: device %d, request %04X\n",i,cmd));
switch (cmd) /* Sun-compatible */
{
case DDIOCSDBG: /* DDI Debug */
if (! suser()) return (-EPERM);
i = verify_area(VERIFY_READ, (int *) arg, sizeof(int));
if (i>=0) i=sbpcd_dbg_ioctl(arg,1);
return (i);
case CDROMPAUSE: /* Pause the drive */
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPAUSE entered.\n"));
/* pause the drive unit when it is currently in PLAY mode, */
/* or reset the starting and ending locations when in PAUSED mode. */
/* If applicable, at the next stopping point it reaches */
/* the drive will discontinue playing. */
switch (DS[d].audio_state)
{
case audio_playing:
i=xx_Pause_Resume(1);
if (i<0) return (-EIO);
DS[d].audio_state=audio_pausing;
i=xx_ReadSubQ();
if (i<0) return (-EIO);
DS[d].pos_audio_start=DS[d].SubQ_run_tot;
return (0);
case audio_pausing:
i=xx_Seek(DS[d].pos_audio_start,1);
if (i<0) return (-EIO);
return (0);
default:
return (-EINVAL);
}
case CDROMRESUME: /* resume paused audio play */
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMRESUME entered.\n"));
/* resume playing audio tracks when a previous PLAY AUDIO call has */
/* been paused with a PAUSE command. */
/* It will resume playing from the location saved in SubQ_run_tot. */
if (DS[d].audio_state!=audio_pausing) return -EINVAL;
i=xx_Pause_Resume(3);
if (i<0) return (-EIO);
DS[d].audio_state=audio_playing;
return (0);
case CDROMPLAYMSF:
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPLAYMSF entered.\n"));
if (DS[d].audio_state==audio_playing)
{
i=xx_Pause_Resume(1);
if (i<0) return (-EIO);
i=xx_ReadSubQ();
if (i<0) return (-EIO);
DS[d].pos_audio_start=DS[d].SubQ_run_tot;
i=xx_Seek(DS[d].pos_audio_start,1);
}
st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_msf));
if (st) return (st);
memcpy_fromfs(&msf, (void *) arg, sizeof(struct cdrom_msf));
/* values come as msf-bin */
DS[d].pos_audio_start = (msf.cdmsf_min0<<16) |
(msf.cdmsf_sec0<<8) |
msf.cdmsf_frame0;
DS[d].pos_audio_end = (msf.cdmsf_min1<<16) |
(msf.cdmsf_sec1<<8) |
msf.cdmsf_frame1;
DPRINTF((DBG_IOX,"SBPCD: ioctl: CDROMPLAYMSF %08X %08X\n",
DS[d].pos_audio_start,DS[d].pos_audio_end));
i=xx_PlayAudioMSF(DS[d].pos_audio_start,DS[d].pos_audio_end);
DPRINTF((DBG_IOC,"SBPCD: ioctl: xx_PlayAudioMSF returns %d\n",i));
#if 0
if (i<0) return (-EIO);
#endif 0
DS[d].audio_state=audio_playing;
return (0);
case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMPLAYTRKIND entered.\n"));
if (DS[d].audio_state==audio_playing)
{
DPRINTF((DBG_IOX,"SBPCD: CDROMPLAYTRKIND: already audio_playing.\n"));
return (0);
return (-EINVAL);
}
st=verify_area(VERIFY_READ,(void *) arg,sizeof(struct cdrom_ti));
if (st<0)
{
DPRINTF((DBG_IOX,"SBPCD: CDROMPLAYTRKIND: verify_area error.\n"));
return (st);
}
memcpy_fromfs(&ti,(void *) arg,sizeof(struct cdrom_ti));
DPRINTF((DBG_IOX,"SBPCD: ioctl: trk0: %d, ind0: %d, trk1:%d, ind1:%d\n",
ti.cdti_trk0,ti.cdti_ind0,ti.cdti_trk1,ti.cdti_ind1));
if (ti.cdti_trk0<DS[d].n_first_track) return (-EINVAL);
if (ti.cdti_trk0>DS[d].n_last_track) return (-EINVAL);
if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
if (ti.cdti_trk1>DS[d].n_last_track) ti.cdti_trk1=DS[d].n_last_track;
DS[d].pos_audio_start=DS[d].TocBuffer[ti.cdti_trk0].address;
DS[d].pos_audio_end=DS[d].TocBuffer[ti.cdti_trk1+1].address;
i=xx_PlayAudioMSF(DS[d].pos_audio_start,DS[d].pos_audio_end);
#if 0
if (i<0) return (-EIO);
#endif 0
DS[d].audio_state=audio_playing;
return (0);
case CDROMREADTOCHDR: /* Read the table of contents header */
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADTOCHDR entered.\n"));
tochdr.cdth_trk0=DS[d].n_first_track;
tochdr.cdth_trk1=DS[d].n_last_track;
st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_tochdr));
if (st) return (st);
memcpy_tofs((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
return (0);
case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADTOCENTRY entered.\n"));
st=verify_area(VERIFY_READ, (void *) arg, sizeof(struct cdrom_tocentry));
if (st) return (st);
memcpy_fromfs(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
i=tocentry.cdte_track;
if (i==CDROM_LEADOUT) i=DS[d].n_last_track+1;
else if (i<DS[d].n_first_track||i>DS[d].n_last_track) return (-EINVAL);
tocentry.cdte_adr=DS[d].TocBuffer[i].ctl_adr&0x0F;
tocentry.cdte_ctrl=(DS[d].TocBuffer[i].ctl_adr>>4)&0x0F;
tocentry.cdte_datamode=DS[d].TocBuffer[i].format;
if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
{ tocentry.cdte_addr.msf.minute=(DS[d].TocBuffer[i].address>>16)&0x00FF;
tocentry.cdte_addr.msf.second=(DS[d].TocBuffer[i].address>>8)&0x00FF;
tocentry.cdte_addr.msf.frame=DS[d].TocBuffer[i].address&0x00FF;
}
else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
tocentry.cdte_addr.lba=msf2blk(DS[d].TocBuffer[i].address);
else return (-EINVAL);
st=verify_area(VERIFY_WRITE,(void *) arg, sizeof(struct cdrom_tocentry));
if (st) return (st);
memcpy_tofs((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
return (0);
case CDROMSTOP: /* Spin down the drive */
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMSTOP entered.\n"));
i=DriveReset();
#if WORKMAN
DS[d].CD_changed=0xFF;
DS[d].diskstate_flags=0;
#endif WORKMAN
DPRINTF((DBG_IOC,"SBPCD: ioctl: DriveReset returns %d\n",i));
DS[d].audio_state=0;
i=DiskInfo();
return (0);
case CDROMSTART: /* Spin up the drive */
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMSTART entered.\n"));
i=xx_SpinUp();
DS[d].audio_state=0;
return (0);
case CDROMEJECT:
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMEJECT entered.\n"));
if (!new_drive) return (0);
#if WORKMAN
DS[d].CD_changed=0xFF;
DS[d].diskstate_flags=0;
#endif WORKMAN
i=yy_SpinDown();
if (i<0) return (-EIO);
DS[d].audio_state=0;
return (0);
case CDROMVOLCTRL: /* Volume control */
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMVOLCTRL entered.\n"));
st=verify_area(VERIFY_READ,(void *) arg,sizeof(volctrl));
if (st) return (st);
memcpy_fromfs(&volctrl,(char *) arg,sizeof(volctrl));
DS[d].vol_chan0=0;
DS[d].vol_ctrl0=volctrl.channel0;
DS[d].vol_chan1=1;
DS[d].vol_ctrl1=volctrl.channel1;
i=xx_SetVolume();
return (0);
case CDROMSUBCHNL: /* Get subchannel info */
DPRINTF((DBG_IOS,"SBPCD: ioctl: CDROMSUBCHNL entered.\n"));
if ((st_spinning)||(!subq_valid)) { i=xx_ReadSubQ();
if (i<0) return (-EIO);
}
st=verify_area(VERIFY_WRITE, (void *) arg, sizeof(struct cdrom_subchnl));
if (st) return (st);
memcpy_fromfs(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
#if 0
if (DS[d].SubQ_audio==0x80) DS[d].SubQ_audio=CDROM_AUDIO_NO_STATUS;
#endif
switch (DS[d].audio_state)
{
case audio_playing:
SC.cdsc_audiostatus=CDROM_AUDIO_PLAY;
break;
case audio_pausing:
SC.cdsc_audiostatus=CDROM_AUDIO_PAUSED;
break;
default:
SC.cdsc_audiostatus=CDROM_AUDIO_NO_STATUS;
break;
}
SC.cdsc_adr=DS[d].SubQ_ctl_adr;
SC.cdsc_ctrl=DS[d].SubQ_ctl_adr>>4;
SC.cdsc_trk=bcd2bin(DS[d].SubQ_trk);
SC.cdsc_ind=bcd2bin(DS[d].SubQ_pnt_idx);
if (SC.cdsc_format==CDROM_LBA)
{
SC.cdsc_absaddr.lba=msf2blk(DS[d].SubQ_run_tot);
SC.cdsc_reladdr.lba=msf2blk(DS[d].SubQ_run_trk);
}
else /* not only if (SC.cdsc_format==CDROM_MSF) */
{
SC.cdsc_absaddr.msf.minute=(DS[d].SubQ_run_tot>>16)&0x00FF;
SC.cdsc_absaddr.msf.second=(DS[d].SubQ_run_tot>>8)&0x00FF;
SC.cdsc_absaddr.msf.frame=DS[d].SubQ_run_tot&0x00FF;
SC.cdsc_reladdr.msf.minute=(DS[d].SubQ_run_trk>>16)&0x00FF;
SC.cdsc_reladdr.msf.second=(DS[d].SubQ_run_trk>>8)&0x00FF;
SC.cdsc_reladdr.msf.frame=DS[d].SubQ_run_trk&0x00FF;
}
memcpy_tofs((void *) arg, &SC, sizeof(struct cdrom_subchnl));
DPRINTF((DBG_IOS,"SBPCD: CDROMSUBCHNL: %1X %02X %08X %08X %02X %02X %06X %06X\n",
SC.cdsc_format,SC.cdsc_audiostatus,
SC.cdsc_adr,SC.cdsc_ctrl,
SC.cdsc_trk,SC.cdsc_ind,
SC.cdsc_absaddr,SC.cdsc_reladdr));
return (0);
case CDROMREADMODE2:
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADMODE2 requested.\n"));
return (-EINVAL);
case CDROMREADMODE1:
DPRINTF((DBG_IOC,"SBPCD: ioctl: CDROMREADMODE1 requested.\n"));
return (-EINVAL);
default:
DPRINTF((DBG_IOC,"SBPCD: ioctl: unknown function request %04X\n", cmd));
return (-EINVAL);
} /* end switch(cmd) */
}
/*==========================================================================*/
/*
* Take care of the different block sizes between cdrom and Linux.
* When Linux gets variable block sizes this will probably go away.
*/
static void sbp_transfer(void)
{
long offs;
while ( (CURRENT->nr_sectors > 0) &&
(CURRENT->sector/4 >= DS[d].sbp_first_frame) &&
(CURRENT->sector/4 <= DS[d].sbp_last_frame) )
{
offs = (CURRENT->sector - DS[d].sbp_first_frame * 4) * 512;
memcpy(CURRENT->buffer, DS[d].sbp_buf + offs, 512);
CURRENT->nr_sectors--;
CURRENT->sector++;
CURRENT->buffer += 512;
}
}
/*==========================================================================*/
/*
* We seem to get never an interrupt.
*/
#if SBPCD_USE_IRQ
static void sbpcd_interrupt(int unused)
{
int st;
st = inb(CDi_status) & 0xFF;
DPRINTF((DBG_IRQ,"SBPCD: INTERRUPT received - CDi_status=%02X\n", st));
}
#endif SBPCD_USE_IRQ
/*==========================================================================*/
/*
* Called from the timer to check the results of the get-status cmd.
*/
static int sbp_status(void)
{
int st;
st=ResponseStatus();
if (st<0)
{
DPRINTF((DBG_INF,"SBPCD: sbp_status: timeout.\n"));
return (0);
}
if (!st_spinning) DPRINTF((DBG_SPI,"SBPCD: motor got off - ignoring.\n"));
if (st_check)
{
DPRINTF((DBG_INF,"SBPCD: st_check detected - retrying.\n"));
return (0);
}
if (!st_door_closed)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -