提交 6a2900b6 编写于 作者: C Christoph Hellwig 提交者: Linus Torvalds

[PATCH] kill cdrom ->dev_ioctl method

Since early 2.4.x all cdrom drivers implement the block_device methods
themselves, so they can handle additional ioctls directly instead of going
through the cdrom layer.
Signed-off-by: NChristoph Hellwig <hch@lst.de>
Acked-by: NJens Axboe <axboe@suse.de>
Signed-off-by: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 d2c5d4fc
...@@ -407,7 +407,6 @@ int register_cdrom(struct cdrom_device_info *cdi) ...@@ -407,7 +407,6 @@ int register_cdrom(struct cdrom_device_info *cdi)
ENSURE(get_mcn, CDC_MCN); ENSURE(get_mcn, CDC_MCN);
ENSURE(reset, CDC_RESET); ENSURE(reset, CDC_RESET);
ENSURE(audio_ioctl, CDC_PLAY_AUDIO); ENSURE(audio_ioctl, CDC_PLAY_AUDIO);
ENSURE(dev_ioctl, CDC_IOCTLS);
ENSURE(generic_packet, CDC_GENERIC_PACKET); ENSURE(generic_packet, CDC_GENERIC_PACKET);
cdi->mc_flags = 0; cdi->mc_flags = 0;
cdo->n_minors = 0; cdo->n_minors = 0;
...@@ -2776,12 +2775,6 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi, ...@@ -2776,12 +2775,6 @@ int cdrom_ioctl(struct file * file, struct cdrom_device_info *cdi,
return cdrom_ioctl_audioctl(cdi, cmd); return cdrom_ioctl_audioctl(cdi, cmd);
} }
/*
* Finally, do the device specific ioctls
*/
if (CDROM_CAN(CDC_IOCTLS))
return cdi->ops->dev_ioctl(cdi, cmd, arg);
return -ENOSYS; return -ENOSYS;
} }
......
...@@ -2668,7 +2668,7 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi, ...@@ -2668,7 +2668,7 @@ static int scd_audio_ioctl(struct cdrom_device_info *cdi,
return retval; return retval;
} }
static int scd_dev_ioctl(struct cdrom_device_info *cdi, static int scd_read_audio(struct cdrom_device_info *cdi,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
...@@ -2894,11 +2894,10 @@ static struct cdrom_device_ops scd_dops = { ...@@ -2894,11 +2894,10 @@ static struct cdrom_device_ops scd_dops = {
.get_mcn = scd_get_mcn, .get_mcn = scd_get_mcn,
.reset = scd_reset, .reset = scd_reset,
.audio_ioctl = scd_audio_ioctl, .audio_ioctl = scd_audio_ioctl,
.dev_ioctl = scd_dev_ioctl,
.capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK | .capability = CDC_OPEN_TRAY | CDC_CLOSE_TRAY | CDC_LOCK |
CDC_SELECT_SPEED | CDC_MULTI_SESSION | CDC_SELECT_SPEED | CDC_MULTI_SESSION |
CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO |
CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS, CDC_RESET | CDC_DRIVE_STATUS,
.n_minors = 1, .n_minors = 1,
}; };
...@@ -2936,6 +2935,9 @@ static int scd_block_ioctl(struct inode *inode, struct file *file, ...@@ -2936,6 +2935,9 @@ static int scd_block_ioctl(struct inode *inode, struct file *file,
case CDROMCLOSETRAY: case CDROMCLOSETRAY:
retval = scd_tray_move(&scd_info, 0); retval = scd_tray_move(&scd_info, 0);
break; break;
case CDROMREADAUDIO:
retval = scd_read_audio(&scd_info, CDROMREADAUDIO, arg);
break;
default: default:
retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg); retval = cdrom_ioctl(file, &scd_info, inode, cmd, arg);
} }
......
...@@ -1157,32 +1157,6 @@ static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, ...@@ -1157,32 +1157,6 @@ static int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
} }
} }
/* Ioctl. These ioctls are specific to the cm206 driver. I have made
some driver statistics accessible through ioctl calls.
*/
static int cm206_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
unsigned long arg)
{
switch (cmd) {
#ifdef STATISTICS
case CM206CTL_GET_STAT:
if (arg >= NR_STATS)
return -EINVAL;
else
return cd->stats[arg];
case CM206CTL_GET_LAST_STAT:
if (arg >= NR_STATS)
return -EINVAL;
else
return cd->last_stat[arg];
#endif
default:
debug(("Unknown ioctl call 0x%x\n", cmd));
return -EINVAL;
}
}
static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr) static int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
{ {
if (cd != NULL) { if (cd != NULL) {
...@@ -1321,11 +1295,10 @@ static struct cdrom_device_ops cm206_dops = { ...@@ -1321,11 +1295,10 @@ static struct cdrom_device_ops cm206_dops = {
.get_mcn = cm206_get_upc, .get_mcn = cm206_get_upc,
.reset = cm206_reset, .reset = cm206_reset,
.audio_ioctl = cm206_audio_ioctl, .audio_ioctl = cm206_audio_ioctl,
.dev_ioctl = cm206_ioctl,
.capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED | CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
CDC_IOCTLS | CDC_DRIVE_STATUS, CDC_DRIVE_STATUS,
.n_minors = 1, .n_minors = 1,
}; };
...@@ -1350,6 +1323,21 @@ static int cm206_block_release(struct inode *inode, struct file *file) ...@@ -1350,6 +1323,21 @@ static int cm206_block_release(struct inode *inode, struct file *file)
static int cm206_block_ioctl(struct inode *inode, struct file *file, static int cm206_block_ioctl(struct inode *inode, struct file *file,
unsigned cmd, unsigned long arg) unsigned cmd, unsigned long arg)
{ {
switch (cmd) {
#ifdef STATISTICS
case CM206CTL_GET_STAT:
if (arg >= NR_STATS)
return -EINVAL;
return cd->stats[arg];
case CM206CTL_GET_LAST_STAT:
if (arg >= NR_STATS)
return -EINVAL;
return cd->last_stat[arg];
#endif
default:
break;
}
return cdrom_ioctl(file, &cm206_info, inode, cmd, arg); return cdrom_ioctl(file, &cm206_info, inode, cmd, arg);
} }
......
...@@ -4160,18 +4160,13 @@ static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_mu ...@@ -4160,18 +4160,13 @@ static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_mu
return 0; return 0;
} }
/*==========================================================================*/ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
/*==========================================================================*/ void * arg)
/*
* ioctl support
*/
static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
u_long arg)
{ {
struct sbpcd_drive *p = cdi->handle; struct sbpcd_drive *p = cdi->handle;
int i; int i, st, j;
msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg); msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg);
if (p->drv_id==-1) { if (p->drv_id==-1) {
msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name); msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
return (-ENXIO); /* no such drive */ return (-ENXIO); /* no such drive */
...@@ -4183,459 +4178,138 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, ...@@ -4183,459 +4178,138 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd); msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
switch (cmd) /* Sun-compatible */ switch (cmd) /* Sun-compatible */
{ {
case DDIOCSDBG: /* DDI Debug */
if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
i=sbpcd_dbg_ioctl(arg,1);
RETURN_UP(i);
case CDROMRESET: /* hard reset the drive */
msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
i=DriveReset();
current_drive->audio_state=0;
RETURN_UP(i);
case CDROMREADMODE1: case CDROMPAUSE: /* Pause the drive */
msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n"); msg(DBG_IOC,"ioctl: CDROMPAUSE entered.\n");
#ifdef SAFE_MIXED /* pause the drive unit when it is currently in PLAY mode, */
if (current_drive->has_data>1) RETURN_UP(-EBUSY); /* or reset the starting and ending locations when in PAUSED mode. */
#endif /* SAFE_MIXED */ /* If applicable, at the next stopping point it reaches */
cc_ModeSelect(CD_FRAMESIZE); /* the drive will discontinue playing. */
cc_ModeSense(); switch (current_drive->audio_state)
current_drive->mode=READ_M1; {
case audio_playing:
if (famL_drive) i=cc_ReadSubQ();
else i=cc_Pause_Resume(1);
if (i<0) RETURN_UP(-EIO);
if (famL_drive) i=cc_Pause_Resume(1);
else i=cc_ReadSubQ();
if (i<0) RETURN_UP(-EIO);
current_drive->pos_audio_start=current_drive->SubQ_run_tot;
current_drive->audio_state=audio_pausing;
RETURN_UP(0);
case audio_pausing:
i=cc_Seek(current_drive->pos_audio_start,1);
if (i<0) RETURN_UP(-EIO);
RETURN_UP(0); RETURN_UP(0);
default:
RETURN_UP(-EINVAL);
}
case CDROMREADMODE2: /* not usable at the moment */ case CDROMRESUME: /* resume paused audio play */
msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); msg(DBG_IOC,"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 (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL);
if (famL_drive)
i=cc_PlayAudio(current_drive->pos_audio_start,
current_drive->pos_audio_end);
else i=cc_Pause_Resume(3);
if (i<0) RETURN_UP(-EIO);
current_drive->audio_state=audio_playing;
RETURN_UP(0);
case CDROMPLAYMSF:
msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
#ifdef SAFE_MIXED #ifdef SAFE_MIXED
if (current_drive->has_data>1) RETURN_UP(-EBUSY); if (current_drive->has_data>1) RETURN_UP(-EBUSY);
#endif /* SAFE_MIXED */ #endif /* SAFE_MIXED */
cc_ModeSelect(CD_FRAMESIZE_RAW1); if (current_drive->audio_state==audio_playing)
cc_ModeSense();
current_drive->mode=READ_M2;
RETURN_UP(0);
case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
if (current_drive->sbp_audsiz>0)
vfree(current_drive->aud_buf);
current_drive->aud_buf=NULL;
current_drive->sbp_audsiz=arg;
if (current_drive->sbp_audsiz>16)
{ {
current_drive->sbp_audsiz = 0; i=cc_Pause_Resume(1);
RETURN_UP(current_drive->sbp_audsiz); if (i<0) RETURN_UP(-EIO);
i=cc_ReadSubQ();
if (i<0) RETURN_UP(-EIO);
current_drive->pos_audio_start=current_drive->SubQ_run_tot;
i=cc_Seek(current_drive->pos_audio_start,1);
} }
memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf));
if (current_drive->sbp_audsiz>0) /* values come as msf-bin */
{ current_drive->pos_audio_start = (msf.cdmsf_min0<<16) |
current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW); (msf.cdmsf_sec0<<8) |
if (current_drive->aud_buf==NULL) msf.cdmsf_frame0;
current_drive->pos_audio_end = (msf.cdmsf_min1<<16) |
(msf.cdmsf_sec1<<8) |
msf.cdmsf_frame1;
msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n",
current_drive->pos_audio_start,current_drive->pos_audio_end);
i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
if (i<0)
{ {
msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz); msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
current_drive->sbp_audsiz=0; DriveReset();
} current_drive->audio_state=0;
else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz); RETURN_UP(-EIO);
} }
RETURN_UP(current_drive->sbp_audsiz); current_drive->audio_state=audio_playing;
RETURN_UP(0);
case CDROMREADAUDIO:
{ /* start of CDROMREADAUDIO */
int i=0, j=0, frame, block=0;
u_int try=0;
u_long timeout;
u_char *p;
u_int data_tries = 0;
u_int data_waits = 0;
u_int data_retrying = 0;
int status_tries;
int error_flag;
msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n"); case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
if (fam0_drive) RETURN_UP(-EINVAL); msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
if (famL_drive) RETURN_UP(-EINVAL);
if (famV_drive) RETURN_UP(-EINVAL);
if (famT_drive) RETURN_UP(-EINVAL);
#ifdef SAFE_MIXED #ifdef SAFE_MIXED
if (current_drive->has_data>1) RETURN_UP(-EBUSY); if (current_drive->has_data>1) RETURN_UP(-EBUSY);
#endif /* SAFE_MIXED */ #endif /* SAFE_MIXED */
if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL); if (current_drive->audio_state==audio_playing)
if (copy_from_user(&read_audio, (void __user *)arg,
sizeof(struct cdrom_read_audio)))
RETURN_UP(-EFAULT);
if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL);
if (!access_ok(VERIFY_WRITE, read_audio.buf,
read_audio.nframes*CD_FRAMESIZE_RAW))
RETURN_UP(-EFAULT);
if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
block=msf2lba(&read_audio.addr.msf.minute);
else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
block=read_audio.addr.lba;
else RETURN_UP(-EINVAL);
#if 000
i=cc_SetSpeed(speed_150,0,0);
if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i);
#endif
msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n",
block, blk2msf(block));
msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n");
#if OLD_BUSY
while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
busy_audio=1;
#endif /* OLD_BUSY */
error_flag=0;
for (data_tries=5; data_tries>0; data_tries--)
{
msg(DBG_AUD,"data_tries=%d ...\n", data_tries);
current_drive->mode=READ_AU;
cc_ModeSelect(CD_FRAMESIZE_RAW);
cc_ModeSense();
for (status_tries=3; status_tries > 0; status_tries--)
{ {
flags_cmd_out |= f_respo3; msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
cc_ReadStatus(); #if 1
if (sbp_status() != 0) break; RETURN_UP(0); /* just let us play on */
if (st_check) cc_ReadError(); #else
sbp_sleep(1); /* wait a bit, try again */ RETURN_UP(-EINVAL); /* play on, but say "error" */
#endif
} }
if (status_tries == 0) memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti));
msg(DBG_IOX,"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<current_drive->n_first_track) RETURN_UP(-EINVAL);
if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL);
if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track;
current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address;
current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address;
i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
if (i<0)
{ {
msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__); msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
continue; DriveReset();
current_drive->audio_state=0;
RETURN_UP(-EIO);
} }
msg(DBG_AUD,"read_audio: sbp_status: ok.\n"); current_drive->audio_state=audio_playing;
RETURN_UP(0);
flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; case CDROMREADTOCHDR: /* Read the table of contents header */
if (fam0L_drive) msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
{ tochdr.cdth_trk0=current_drive->n_first_track;
flags_cmd_out |= f_lopsta | f_getsta | f_bit1; tochdr.cdth_trk1=current_drive->n_last_track;
cmd_type=READ_M2; memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ RETURN_UP(0);
drvcmd[1]=(block>>16)&0x000000ff;
drvcmd[2]=(block>>8)&0x000000ff; case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
drvcmd[3]=block&0x000000ff; msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
drvcmd[4]=0; memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
drvcmd[5]=read_audio.nframes; /* # of frames */ i=tocentry.cdte_track;
drvcmd[6]=0; if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1;
} else if (i<current_drive->n_first_track||i>current_drive->n_last_track)
else if (fam1_drive) RETURN_UP(-EINVAL);
{ tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F;
drvcmd[0]=CMD1_READ; /* "read frames", new drives */ tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F;
lba2msf(block,&drvcmd[1]); /* msf-bin format required */ tocentry.cdte_datamode=current_drive->TocBuffer[i].format;
drvcmd[4]=0; if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
drvcmd[5]=0;
drvcmd[6]=read_audio.nframes; /* # of frames */
}
else if (fam2_drive)
{
drvcmd[0]=CMD2_READ_XA2;
lba2msf(block,&drvcmd[1]); /* msf-bin format required */
drvcmd[4]=0;
drvcmd[5]=read_audio.nframes; /* # of frames */
drvcmd[6]=0x11; /* raw mode */
}
else if (famT_drive) /* CD-55A: not tested yet */
{ {
} tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF;
msg(DBG_AUD,"read_audio: before giving \"read\" command.\n"); tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF;
flags_cmd_out=f_putcmd; tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF;
response_count=0;
i=cmd_out();
if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i);
sbp_sleep(0);
msg(DBG_AUD,"read_audio: after giving \"read\" command.\n");
for (frame=1;frame<2 && !error_flag; frame++)
{
try=maxtim_data;
for (timeout=jiffies+9*HZ; ; )
{
for ( ; try!=0;try--)
{
j=inb(CDi_status);
if (!(j&s_not_data_ready)) break;
if (!(j&s_not_result_ready)) break;
if (fam0L_drive) if (j&s_attention) break;
}
if (try != 0 || time_after_eq(jiffies, timeout)) break;
if (data_retrying == 0) data_waits++;
data_retrying = 1;
sbp_sleep(1);
try = 1;
}
if (try==0)
{
msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n");
error_flag++;
break;
}
msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n");
if (j&s_not_data_ready)
{
msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n");
error_flag++;
break;
}
msg(DBG_AUD,"read_audio: before reading data.\n");
error_flag=0;
p = current_drive->aud_buf;
if (sbpro_type==1) OUT(CDo_sel_i_d,1);
if (do_16bit)
{
u_short *p2 = (u_short *) p;
for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
{
if ((inb_p(CDi_status)&s_not_data_ready)) continue;
/* get one sample */
*p2++ = inw_p(CDi_data);
*p2++ = inw_p(CDi_data);
}
} else {
for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
{
if ((inb_p(CDi_status)&s_not_data_ready)) continue;
/* get one sample */
*p++ = inb_p(CDi_data);
*p++ = inb_p(CDi_data);
*p++ = inb_p(CDi_data);
*p++ = inb_p(CDi_data);
}
}
if (sbpro_type==1) OUT(CDo_sel_i_d,0);
data_retrying = 0;
}
msg(DBG_AUD,"read_audio: after reading data.\n");
if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
{
msg(DBG_AUD,"read_audio: read aborted by drive\n");
#if 0000
i=cc_DriveReset(); /* ugly fix to prevent a hang */
#else
i=cc_ReadError();
#endif
continue;
}
if (fam0L_drive)
{
i=maxtim_data;
for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
{
for ( ;i!=0;i--)
{
j=inb(CDi_status);
if (!(j&s_not_data_ready)) break;
if (!(j&s_not_result_ready)) break;
if (j&s_attention) break;
}
if (i != 0 || time_after_eq(jiffies, timeout)) break;
sbp_sleep(0);
i = 1;
}
if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ");
if (!(j&s_attention))
{
msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n");
i=cc_DriveReset(); /* ugly fix to prevent a hang */
continue;
}
}
do
{
if (fam0L_drive) cc_ReadStatus();
i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
if (i<0) { msg(DBG_AUD,
"read_audio: cc_ReadStatus error after read: %02X\n",
current_drive->status_bits);
continue; /* FIXME */
}
}
while ((fam0L_drive)&&(!st_check)&&(!(i&p_success)));
if (st_check)
{
i=cc_ReadError();
msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i);
continue;
}
if (copy_to_user(read_audio.buf,
current_drive->aud_buf,
read_audio.nframes * CD_FRAMESIZE_RAW))
RETURN_UP(-EFAULT);
msg(DBG_AUD,"read_audio: copy_to_user done.\n");
break;
}
cc_ModeSelect(CD_FRAMESIZE);
cc_ModeSense();
current_drive->mode=READ_M1;
#if OLD_BUSY
busy_audio=0;
#endif /* OLD_BUSY */
if (data_tries == 0)
{
msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
RETURN_UP(-EIO);
}
msg(DBG_AUD,"read_audio: successful return.\n");
RETURN_UP(0);
} /* end of CDROMREADAUDIO */
default:
msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
RETURN_UP(-EINVAL);
} /* end switch(cmd) */
}
static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
void * arg)
{
struct sbpcd_drive *p = cdi->handle;
int i, st, j;
msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08p)\n", cdi->name, cmd, arg);
if (p->drv_id==-1) {
msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
return (-ENXIO); /* no such drive */
}
down(&ioctl_read_sem);
if (p != current_drive)
switch_drive(p);
msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
switch (cmd) /* Sun-compatible */
{
case CDROMPAUSE: /* Pause the drive */
msg(DBG_IOC,"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 (current_drive->audio_state)
{
case audio_playing:
if (famL_drive) i=cc_ReadSubQ();
else i=cc_Pause_Resume(1);
if (i<0) RETURN_UP(-EIO);
if (famL_drive) i=cc_Pause_Resume(1);
else i=cc_ReadSubQ();
if (i<0) RETURN_UP(-EIO);
current_drive->pos_audio_start=current_drive->SubQ_run_tot;
current_drive->audio_state=audio_pausing;
RETURN_UP(0);
case audio_pausing:
i=cc_Seek(current_drive->pos_audio_start,1);
if (i<0) RETURN_UP(-EIO);
RETURN_UP(0);
default:
RETURN_UP(-EINVAL);
}
case CDROMRESUME: /* resume paused audio play */
msg(DBG_IOC,"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 (current_drive->audio_state!=audio_pausing) RETURN_UP(-EINVAL);
if (famL_drive)
i=cc_PlayAudio(current_drive->pos_audio_start,
current_drive->pos_audio_end);
else i=cc_Pause_Resume(3);
if (i<0) RETURN_UP(-EIO);
current_drive->audio_state=audio_playing;
RETURN_UP(0);
case CDROMPLAYMSF:
msg(DBG_IOC,"ioctl: CDROMPLAYMSF entered.\n");
#ifdef SAFE_MIXED
if (current_drive->has_data>1) RETURN_UP(-EBUSY);
#endif /* SAFE_MIXED */
if (current_drive->audio_state==audio_playing)
{
i=cc_Pause_Resume(1);
if (i<0) RETURN_UP(-EIO);
i=cc_ReadSubQ();
if (i<0) RETURN_UP(-EIO);
current_drive->pos_audio_start=current_drive->SubQ_run_tot;
i=cc_Seek(current_drive->pos_audio_start,1);
}
memcpy(&msf, (void *) arg, sizeof(struct cdrom_msf));
/* values come as msf-bin */
current_drive->pos_audio_start = (msf.cdmsf_min0<<16) |
(msf.cdmsf_sec0<<8) |
msf.cdmsf_frame0;
current_drive->pos_audio_end = (msf.cdmsf_min1<<16) |
(msf.cdmsf_sec1<<8) |
msf.cdmsf_frame1;
msg(DBG_IOX,"ioctl: CDROMPLAYMSF %08X %08X\n",
current_drive->pos_audio_start,current_drive->pos_audio_end);
i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
if (i<0)
{
msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
DriveReset();
current_drive->audio_state=0;
RETURN_UP(-EIO);
}
current_drive->audio_state=audio_playing;
RETURN_UP(0);
case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
#ifdef SAFE_MIXED
if (current_drive->has_data>1) RETURN_UP(-EBUSY);
#endif /* SAFE_MIXED */
if (current_drive->audio_state==audio_playing)
{
msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
#if 1
RETURN_UP(0); /* just let us play on */
#else
RETURN_UP(-EINVAL); /* play on, but say "error" */
#endif
}
memcpy(&ti,(void *) arg,sizeof(struct cdrom_ti));
msg(DBG_IOX,"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<current_drive->n_first_track) RETURN_UP(-EINVAL);
if (ti.cdti_trk0>current_drive->n_last_track) RETURN_UP(-EINVAL);
if (ti.cdti_trk1<ti.cdti_trk0) ti.cdti_trk1=ti.cdti_trk0;
if (ti.cdti_trk1>current_drive->n_last_track) ti.cdti_trk1=current_drive->n_last_track;
current_drive->pos_audio_start=current_drive->TocBuffer[ti.cdti_trk0].address;
current_drive->pos_audio_end=current_drive->TocBuffer[ti.cdti_trk1+1].address;
i=cc_PlayAudio(current_drive->pos_audio_start,current_drive->pos_audio_end);
if (i<0)
{
msg(DBG_INF,"ioctl: cc_PlayAudio returns %d\n",i);
DriveReset();
current_drive->audio_state=0;
RETURN_UP(-EIO);
}
current_drive->audio_state=audio_playing;
RETURN_UP(0);
case CDROMREADTOCHDR: /* Read the table of contents header */
msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
tochdr.cdth_trk0=current_drive->n_first_track;
tochdr.cdth_trk1=current_drive->n_last_track;
memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
RETURN_UP(0);
case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
i=tocentry.cdte_track;
if (i==CDROM_LEADOUT) i=current_drive->n_last_track+1;
else if (i<current_drive->n_first_track||i>current_drive->n_last_track)
RETURN_UP(-EINVAL);
tocentry.cdte_adr=current_drive->TocBuffer[i].ctl_adr&0x0F;
tocentry.cdte_ctrl=(current_drive->TocBuffer[i].ctl_adr>>4)&0x0F;
tocentry.cdte_datamode=current_drive->TocBuffer[i].format;
if (tocentry.cdte_format==CDROM_MSF) /* MSF-bin required */
{
tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF;
tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF;
tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF;
} }
else if (tocentry.cdte_format==CDROM_LBA) /* blk required */ else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address); tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address);
...@@ -5098,197 +4772,535 @@ static int sbp_data(struct request *req) ...@@ -5098,197 +4772,535 @@ static int sbp_data(struct request *req)
#if LONG_TIMING #if LONG_TIMING
max_latency=9*HZ; max_latency=9*HZ;
#else #else
if (current_drive->f_multisession) max_latency=15*HZ; if (current_drive->f_multisession) max_latency=15*HZ;
else max_latency=5*HZ; else max_latency=5*HZ;
#endif
duration=jiffies;
for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++)
{
SBPCD_CLI;
del_timer(&data_timer);
data_timer.expires=jiffies+max_latency;
timed_out_data=0;
add_timer(&data_timer);
while (!timed_out_data)
{
if (current_drive->f_multisession) try=maxtim_data*4;
else try=maxtim_data;
msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try);
for ( ; try!=0;try--)
{
j=inb(CDi_status);
if (!(j&s_not_data_ready)) break;
if (!(j&s_not_result_ready)) break;
if (fam0LV_drive) if (j&s_attention) break;
}
if (!(j&s_not_data_ready)) goto data_ready;
if (try==0)
{
if (data_retrying == 0) data_waits++;
data_retrying = 1;
msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n");
sbp_sleep(1);
try = 1;
}
}
msg(DBG_INF,"sbp_data: CDi_status loop expired.\n");
data_ready:
del_timer(&data_timer);
if (timed_out_data)
{
msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j);
error_flag++;
}
if (try==0)
{
msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j);
error_flag++;
}
if (!(j&s_not_result_ready))
{
msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j);
response_count=20;
j=ResponseInfo();
j=inb(CDi_status);
}
if (j&s_not_data_ready)
{
if ((current_drive->ored_ctl_adr&0x40)==0)
msg(DBG_INF, "CD contains no data tracks.\n");
else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j);
error_flag++;
}
SBPCD_STI;
if (error_flag) break;
msg(DBG_000, "sbp_data: beginning to read.\n");
p = current_drive->sbp_buf + frame * CD_FRAMESIZE;
if (sbpro_type==1) OUT(CDo_sel_i_d,1);
if (cmd_type==READ_M2) {
if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1);
else insb(CDi_data, xa_head_buf, CD_XA_HEAD);
}
if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1);
else insb(CDi_data, p, CD_FRAMESIZE);
if (cmd_type==READ_M2) {
if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1);
else insb(CDi_data, xa_tail_buf, CD_XA_TAIL);
}
current_drive->sbp_current++;
if (sbpro_type==1) OUT(CDo_sel_i_d,0);
if (cmd_type==READ_M2)
{
for (xa_count=0;xa_count<CD_XA_HEAD;xa_count++)
sprintf(&msgbuf[xa_count*3], " %02X", xa_head_buf[xa_count]);
msgbuf[xa_count*3]=0;
msg(DBG_XA1,"xa head:%s\n", msgbuf);
}
data_retrying = 0;
data_tries++;
if (data_tries >= 1000)
{
msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries);
data_waits = data_tries = 0;
}
}
duration=jiffies-duration;
msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration);
if (famT_drive)
{
wait=8;
do
{
if (teac==2)
{
if ((i=CDi_stat_loop_T()) == -1) break;
}
else
{
sbp_sleep(1);
OUT(CDo_sel_i_d,0);
i=inb(CDi_status);
}
if (!(i&s_not_data_ready))
{
OUT(CDo_sel_i_d,1);
j=0;
do
{
if (do_16bit) i=inw(CDi_data);
else i=inb(CDi_data);
j++;
i=inb(CDi_status);
}
while (!(i&s_not_data_ready));
msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j);
}
if (!(i&s_not_result_ready))
{
OUT(CDo_sel_i_d,0);
l=0;
do
{
infobuf[l++]=inb(CDi_info);
i=inb(CDi_status);
}
while (!(i&s_not_result_ready));
if (infobuf[0]==0x00) success=1;
#if 1
for (j=0;j<l;j++) sprintf(&msgbuf[j*3], " %02X", infobuf[j]);
msgbuf[j*3]=0;
msg(DBG_TEA,"sbp_data info response:%s\n", msgbuf);
#endif
if (infobuf[0]==0x02)
{
error_flag++;
do
{
++recursion;
if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion);
else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n");
clr_cmdbuf();
drvcmd[0]=CMDT_READ_ERR;
j=cmd_out_T(); /* !!! recursive here !!! */
--recursion;
sbp_sleep(1);
}
while (j<0);
current_drive->error_state=infobuf[2];
current_drive->b3=infobuf[3];
current_drive->b4=infobuf[4];
}
break;
}
else
{
#if 0
msg(DBG_TEA, "============= waiting for result=================.\n");
sbp_sleep(1);
#endif
}
}
while (wait--);
}
if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
{
msg(DBG_TEA, "================error flag: %d=================.\n", error_flag);
msg(DBG_INF,"sbp_data: read aborted by drive.\n");
#if 1
i=cc_DriveReset(); /* ugly fix to prevent a hang */
#else
i=cc_ReadError();
#endif #endif
duration=jiffies; return (0);
for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++) }
if (fam0LV_drive)
{ {
SBPCD_CLI; SBPCD_CLI;
i=maxtim_data;
del_timer(&data_timer); for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
data_timer.expires=jiffies+max_latency;
timed_out_data=0;
add_timer(&data_timer);
while (!timed_out_data)
{ {
if (current_drive->f_multisession) try=maxtim_data*4; for ( ;i!=0;i--)
else try=maxtim_data;
msg(DBG_000,"sbp_data: CDi_status loop: try=%d.\n",try);
for ( ; try!=0;try--)
{ {
j=inb(CDi_status); j=inb(CDi_status);
if (!(j&s_not_data_ready)) break; if (!(j&s_not_data_ready)) break;
if (!(j&s_not_result_ready)) break; if (!(j&s_not_result_ready)) break;
if (fam0LV_drive) if (j&s_attention) break; if (j&s_attention) break;
} }
if (!(j&s_not_data_ready)) goto data_ready; if (i != 0 || time_after_eq(jiffies, timeout)) break;
if (try==0) sbp_sleep(0);
i = 1;
}
if (i==0) msg(DBG_INF,"status timeout after READ.\n");
if (!(j&s_attention))
{ {
if (data_retrying == 0) data_waits++; msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n");
data_retrying = 1; i=cc_DriveReset(); /* ugly fix to prevent a hang */
msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n"); SBPCD_STI;
sbp_sleep(1); return (0);
try = 1;
} }
SBPCD_STI;
} }
msg(DBG_INF,"sbp_data: CDi_status loop expired.\n");
data_ready:
del_timer(&data_timer);
if (timed_out_data) #if 0
if (!success)
#endif
do
{ {
msg(DBG_INF,"sbp_data: CDi_status timeout (timed_out_data) (%02X).\n", j); if (fam0LV_drive) cc_ReadStatus();
error_flag++; #if 1
} if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i);
if (try==0) #endif
i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
#if 1
if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i);
#endif
if (i<0)
{ {
msg(DBG_INF,"sbp_data: CDi_status timeout (try=0) (%02X).\n", j); msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits);
error_flag++; return (0);
} }
if (!(j&s_not_result_ready)) }
while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success)));
if (st_check)
{ {
msg(DBG_INF, "sbp_data: RESULT_READY where DATA_READY awaited (%02X).\n", j); i=cc_ReadError();
response_count=20; msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i);
j=ResponseInfo(); return (0);
j=inb(CDi_status);
} }
if (j&s_not_data_ready) if (fatal_err)
{ {
if ((current_drive->ored_ctl_adr&0x40)==0) fatal_err=0;
msg(DBG_INF, "CD contains no data tracks.\n"); current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */
else msg(DBG_INF, "sbp_data: DATA_READY timeout (%02X).\n", j); current_drive->sbp_current = 0;
error_flag++; msg(DBG_INF,"sbp_data: fatal_err - retrying.\n");
return (0);
} }
SBPCD_STI;
if (error_flag) break;
msg(DBG_000, "sbp_data: beginning to read.\n"); current_drive->sbp_first_frame = req -> sector / 4;
p = current_drive->sbp_buf + frame * CD_FRAMESIZE; current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1;
if (sbpro_type==1) OUT(CDo_sel_i_d,1); sbp_transfer(req);
if (cmd_type==READ_M2) { return (1);
if (do_16bit) insw(CDi_data, xa_head_buf, CD_XA_HEAD>>1); }
else insb(CDi_data, xa_head_buf, CD_XA_HEAD); /*==========================================================================*/
static int sbpcd_block_open(struct inode *inode, struct file *file)
{
struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
return cdrom_open(p->sbpcd_infop, inode, file);
}
static int sbpcd_block_release(struct inode *inode, struct file *file)
{
struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
return cdrom_release(p->sbpcd_infop, file);
}
static int sbpcd_block_ioctl(struct inode *inode, struct file *file,
unsigned cmd, unsigned long arg)
{
struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
struct cdrom_device_info *cdi = p->sbpcd_infop;
int ret, i;
ret = cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg);
if (ret != -ENOSYS)
return ret;
msg(DBG_IO2,"ioctl(%s, 0x%08lX, 0x%08lX)\n", cdi->name, cmd, arg);
if (p->drv_id==-1) {
msg(DBG_INF, "ioctl: bad device: %s\n", cdi->name);
return (-ENXIO); /* no such drive */
} }
if (do_16bit) insw(CDi_data, p, CD_FRAMESIZE>>1); down(&ioctl_read_sem);
else insb(CDi_data, p, CD_FRAMESIZE); if (p != current_drive)
if (cmd_type==READ_M2) { switch_drive(p);
if (do_16bit) insw(CDi_data, xa_tail_buf, CD_XA_TAIL>>1);
else insb(CDi_data, xa_tail_buf, CD_XA_TAIL); msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
switch (cmd) /* Sun-compatible */
{
case DDIOCSDBG: /* DDI Debug */
if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
i=sbpcd_dbg_ioctl(arg,1);
RETURN_UP(i);
case CDROMRESET: /* hard reset the drive */
msg(DBG_IOC,"ioctl: CDROMRESET entered.\n");
i=DriveReset();
current_drive->audio_state=0;
RETURN_UP(i);
case CDROMREADMODE1:
msg(DBG_IOC,"ioctl: CDROMREADMODE1 requested.\n");
#ifdef SAFE_MIXED
if (current_drive->has_data>1) RETURN_UP(-EBUSY);
#endif /* SAFE_MIXED */
cc_ModeSelect(CD_FRAMESIZE);
cc_ModeSense();
current_drive->mode=READ_M1;
RETURN_UP(0);
case CDROMREADMODE2: /* not usable at the moment */
msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n");
#ifdef SAFE_MIXED
if (current_drive->has_data>1) RETURN_UP(-EBUSY);
#endif /* SAFE_MIXED */
cc_ModeSelect(CD_FRAMESIZE_RAW1);
cc_ModeSense();
current_drive->mode=READ_M2;
RETURN_UP(0);
case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */
msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n");
if (current_drive->sbp_audsiz>0)
vfree(current_drive->aud_buf);
current_drive->aud_buf=NULL;
current_drive->sbp_audsiz=arg;
if (current_drive->sbp_audsiz>16)
{
current_drive->sbp_audsiz = 0;
RETURN_UP(current_drive->sbp_audsiz);
} }
current_drive->sbp_current++;
if (sbpro_type==1) OUT(CDo_sel_i_d,0); if (current_drive->sbp_audsiz>0)
if (cmd_type==READ_M2)
{ {
for (xa_count=0;xa_count<CD_XA_HEAD;xa_count++) current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW);
sprintf(&msgbuf[xa_count*3], " %02X", xa_head_buf[xa_count]); if (current_drive->aud_buf==NULL)
msgbuf[xa_count*3]=0; {
msg(DBG_XA1,"xa head:%s\n", msgbuf); msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz);
current_drive->sbp_audsiz=0;
} }
data_retrying = 0; else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz);
data_tries++; }
if (data_tries >= 1000) RETURN_UP(current_drive->sbp_audsiz);
case CDROMREADAUDIO:
{ /* start of CDROMREADAUDIO */
int i=0, j=0, frame, block=0;
u_int try=0;
u_long timeout;
u_char *p;
u_int data_tries = 0;
u_int data_waits = 0;
u_int data_retrying = 0;
int status_tries;
int error_flag;
msg(DBG_IOC,"ioctl: CDROMREADAUDIO entered.\n");
if (fam0_drive) RETURN_UP(-EINVAL);
if (famL_drive) RETURN_UP(-EINVAL);
if (famV_drive) RETURN_UP(-EINVAL);
if (famT_drive) RETURN_UP(-EINVAL);
#ifdef SAFE_MIXED
if (current_drive->has_data>1) RETURN_UP(-EBUSY);
#endif /* SAFE_MIXED */
if (current_drive->aud_buf==NULL) RETURN_UP(-EINVAL);
if (copy_from_user(&read_audio, (void __user *)arg,
sizeof(struct cdrom_read_audio)))
RETURN_UP(-EFAULT);
if (read_audio.nframes < 0 || read_audio.nframes>current_drive->sbp_audsiz) RETURN_UP(-EINVAL);
if (!access_ok(VERIFY_WRITE, read_audio.buf,
read_audio.nframes*CD_FRAMESIZE_RAW))
RETURN_UP(-EFAULT);
if (read_audio.addr_format==CDROM_MSF) /* MSF-bin specification of where to start */
block=msf2lba(&read_audio.addr.msf.minute);
else if (read_audio.addr_format==CDROM_LBA) /* lba specification of where to start */
block=read_audio.addr.lba;
else RETURN_UP(-EINVAL);
#if 000
i=cc_SetSpeed(speed_150,0,0);
if (i) msg(DBG_AUD,"read_audio: SetSpeed error %d\n", i);
#endif
msg(DBG_AUD,"read_audio: lba: %d, msf: %06X\n",
block, blk2msf(block));
msg(DBG_AUD,"read_audio: before cc_ReadStatus.\n");
#if OLD_BUSY
while (busy_data) sbp_sleep(HZ/10); /* wait a bit */
busy_audio=1;
#endif /* OLD_BUSY */
error_flag=0;
for (data_tries=5; data_tries>0; data_tries--)
{
msg(DBG_AUD,"data_tries=%d ...\n", data_tries);
current_drive->mode=READ_AU;
cc_ModeSelect(CD_FRAMESIZE_RAW);
cc_ModeSense();
for (status_tries=3; status_tries > 0; status_tries--)
{ {
msg(DBG_INF,"sbp_data() statistics: %d waits in %d frames.\n", data_waits, data_tries); flags_cmd_out |= f_respo3;
data_waits = data_tries = 0; cc_ReadStatus();
if (sbp_status() != 0) break;
if (st_check) cc_ReadError();
sbp_sleep(1); /* wait a bit, try again */
} }
if (status_tries == 0)
{
msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__);
continue;
} }
duration=jiffies-duration; msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration);
if (famT_drive) flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
if (fam0L_drive)
{ {
wait=8; flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
do cmd_type=READ_M2;
drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
drvcmd[1]=(block>>16)&0x000000ff;
drvcmd[2]=(block>>8)&0x000000ff;
drvcmd[3]=block&0x000000ff;
drvcmd[4]=0;
drvcmd[5]=read_audio.nframes; /* # of frames */
drvcmd[6]=0;
}
else if (fam1_drive)
{ {
if (teac==2) drvcmd[0]=CMD1_READ; /* "read frames", new drives */
lba2msf(block,&drvcmd[1]); /* msf-bin format required */
drvcmd[4]=0;
drvcmd[5]=0;
drvcmd[6]=read_audio.nframes; /* # of frames */
}
else if (fam2_drive)
{ {
if ((i=CDi_stat_loop_T()) == -1) break; drvcmd[0]=CMD2_READ_XA2;
lba2msf(block,&drvcmd[1]); /* msf-bin format required */
drvcmd[4]=0;
drvcmd[5]=read_audio.nframes; /* # of frames */
drvcmd[6]=0x11; /* raw mode */
} }
else else if (famT_drive) /* CD-55A: not tested yet */
{ {
sbp_sleep(1);
OUT(CDo_sel_i_d,0);
i=inb(CDi_status);
} }
if (!(i&s_not_data_ready)) msg(DBG_AUD,"read_audio: before giving \"read\" command.\n");
flags_cmd_out=f_putcmd;
response_count=0;
i=cmd_out();
if (i<0) msg(DBG_INF,"error giving READ AUDIO command: %0d\n", i);
sbp_sleep(0);
msg(DBG_AUD,"read_audio: after giving \"read\" command.\n");
for (frame=1;frame<2 && !error_flag; frame++)
{ {
OUT(CDo_sel_i_d,1); try=maxtim_data;
j=0; for (timeout=jiffies+9*HZ; ; )
do
{ {
if (do_16bit) i=inw(CDi_data); for ( ; try!=0;try--)
else i=inb(CDi_data); {
j++; j=inb(CDi_status);
i=inb(CDi_status); if (!(j&s_not_data_ready)) break;
if (!(j&s_not_result_ready)) break;
if (fam0L_drive) if (j&s_attention) break;
} }
while (!(i&s_not_data_ready)); if (try != 0 || time_after_eq(jiffies, timeout)) break;
msg(DBG_TEA, "==========too much data (%d bytes/words)==============.\n", j); if (data_retrying == 0) data_waits++;
data_retrying = 1;
sbp_sleep(1);
try = 1;
} }
if (!(i&s_not_result_ready)) if (try==0)
{
OUT(CDo_sel_i_d,0);
l=0;
do
{ {
infobuf[l++]=inb(CDi_info); msg(DBG_INF,"read_audio: sbp_data: CDi_status timeout.\n");
i=inb(CDi_status); error_flag++;
break;
} }
while (!(i&s_not_result_ready)); msg(DBG_AUD,"read_audio: sbp_data: CDi_status ok.\n");
if (infobuf[0]==0x00) success=1; if (j&s_not_data_ready)
#if 1
for (j=0;j<l;j++) sprintf(&msgbuf[j*3], " %02X", infobuf[j]);
msgbuf[j*3]=0;
msg(DBG_TEA,"sbp_data info response:%s\n", msgbuf);
#endif
if (infobuf[0]==0x02)
{ {
msg(DBG_INF, "read_audio: sbp_data: DATA_READY timeout.\n");
error_flag++; error_flag++;
do
{
++recursion;
if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion);
else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n");
clr_cmdbuf();
drvcmd[0]=CMDT_READ_ERR;
j=cmd_out_T(); /* !!! recursive here !!! */
--recursion;
sbp_sleep(1);
}
while (j<0);
current_drive->error_state=infobuf[2];
current_drive->b3=infobuf[3];
current_drive->b4=infobuf[4];
}
break; break;
} }
else msg(DBG_AUD,"read_audio: before reading data.\n");
error_flag=0;
p = current_drive->aud_buf;
if (sbpro_type==1) OUT(CDo_sel_i_d,1);
if (do_16bit)
{ {
#if 0 u_short *p2 = (u_short *) p;
msg(DBG_TEA, "============= waiting for result=================.\n");
sbp_sleep(1); for (; (u_char *) p2 < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
#endif {
if ((inb_p(CDi_status)&s_not_data_ready)) continue;
/* get one sample */
*p2++ = inw_p(CDi_data);
*p2++ = inw_p(CDi_data);
}
} else {
for (; p < current_drive->aud_buf + read_audio.nframes*CD_FRAMESIZE_RAW;)
{
if ((inb_p(CDi_status)&s_not_data_ready)) continue;
/* get one sample */
*p++ = inb_p(CDi_data);
*p++ = inb_p(CDi_data);
*p++ = inb_p(CDi_data);
*p++ = inb_p(CDi_data);
} }
} }
while (wait--); if (sbpro_type==1) OUT(CDo_sel_i_d,0);
data_retrying = 0;
} }
msg(DBG_AUD,"read_audio: after reading data.\n");
if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */ if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
{ {
msg(DBG_TEA, "================error flag: %d=================.\n", error_flag); msg(DBG_AUD,"read_audio: read aborted by drive\n");
msg(DBG_INF,"sbp_data: read aborted by drive.\n"); #if 0000
#if 1
i=cc_DriveReset(); /* ugly fix to prevent a hang */ i=cc_DriveReset(); /* ugly fix to prevent a hang */
#else #else
i=cc_ReadError(); i=cc_ReadError();
#endif #endif
return (0); continue;
} }
if (fam0L_drive)
if (fam0LV_drive)
{ {
SBPCD_CLI;
i=maxtim_data; i=maxtim_data;
for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--) for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
{ {
for ( ;i!=0;i--) for ( ;i!=0;i--)
{ {
...@@ -5301,76 +5313,57 @@ static int sbp_data(struct request *req) ...@@ -5301,76 +5313,57 @@ static int sbp_data(struct request *req)
sbp_sleep(0); sbp_sleep(0);
i = 1; i = 1;
} }
if (i==0) msg(DBG_INF,"status timeout after READ.\n"); if (i==0) msg(DBG_AUD,"read_audio: STATUS TIMEOUT AFTER READ");
if (!(j&s_attention)) if (!(j&s_attention))
{ {
msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n"); msg(DBG_AUD,"read_audio: sbp_data: timeout waiting DRV_ATTN - retrying\n");
i=cc_DriveReset(); /* ugly fix to prevent a hang */ i=cc_DriveReset(); /* ugly fix to prevent a hang */
SBPCD_STI; continue;
return (0);
} }
SBPCD_STI;
} }
#if 0
if (!success)
#endif
do do
{ {
if (fam0LV_drive) cc_ReadStatus(); if (fam0L_drive) cc_ReadStatus();
#if 1
if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i);
#endif
i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */ i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
#if 1 if (i<0) { msg(DBG_AUD,
if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i); "read_audio: cc_ReadStatus error after read: %02X\n",
#endif current_drive->status_bits);
if (i<0) continue; /* FIXME */
{
msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits);
return (0);
} }
} }
while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success))); while ((fam0L_drive)&&(!st_check)&&(!(i&p_success)));
if (st_check) if (st_check)
{ {
i=cc_ReadError(); i=cc_ReadError();
msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i); msg(DBG_AUD,"read_audio: cc_ReadError was necessary after read: %02X\n",i);
return (0); continue;
} }
if (fatal_err) if (copy_to_user(read_audio.buf,
current_drive->aud_buf,
read_audio.nframes * CD_FRAMESIZE_RAW))
RETURN_UP(-EFAULT);
msg(DBG_AUD,"read_audio: copy_to_user done.\n");
break;
}
cc_ModeSelect(CD_FRAMESIZE);
cc_ModeSense();
current_drive->mode=READ_M1;
#if OLD_BUSY
busy_audio=0;
#endif /* OLD_BUSY */
if (data_tries == 0)
{ {
fatal_err=0; msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ RETURN_UP(-EIO);
current_drive->sbp_current = 0;
msg(DBG_INF,"sbp_data: fatal_err - retrying.\n");
return (0);
} }
msg(DBG_AUD,"read_audio: successful return.\n");
RETURN_UP(0);
} /* end of CDROMREADAUDIO */
current_drive->sbp_first_frame = req -> sector / 4; default:
current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1; msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
sbp_transfer(req); RETURN_UP(-EINVAL);
return (1); } /* end switch(cmd) */
}
/*==========================================================================*/
static int sbpcd_block_open(struct inode *inode, struct file *file)
{
struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
return cdrom_open(p->sbpcd_infop, inode, file);
}
static int sbpcd_block_release(struct inode *inode, struct file *file)
{
struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
return cdrom_release(p->sbpcd_infop, file);
}
static int sbpcd_block_ioctl(struct inode *inode, struct file *file,
unsigned cmd, unsigned long arg)
{
struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
return cdrom_ioctl(file, p->sbpcd_infop, inode, cmd, arg);
} }
static int sbpcd_block_media_changed(struct gendisk *disk) static int sbpcd_block_media_changed(struct gendisk *disk)
...@@ -5478,10 +5471,9 @@ static struct cdrom_device_ops sbpcd_dops = { ...@@ -5478,10 +5471,9 @@ static struct cdrom_device_ops sbpcd_dops = {
.get_mcn = sbpcd_get_mcn, .get_mcn = sbpcd_get_mcn,
.reset = sbpcd_reset, .reset = sbpcd_reset,
.audio_ioctl = sbpcd_audio_ioctl, .audio_ioctl = sbpcd_audio_ioctl,
.dev_ioctl = sbpcd_dev_ioctl,
.capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
CDC_MCN | CDC_PLAY_AUDIO | CDC_IOCTLS, CDC_MCN | CDC_PLAY_AUDIO,
.n_minors = 1, .n_minors = 1,
}; };
......
...@@ -627,7 +627,7 @@ static struct cdrom_device_ops viocd_dops = { ...@@ -627,7 +627,7 @@ static struct cdrom_device_ops viocd_dops = {
.media_changed = viocd_media_changed, .media_changed = viocd_media_changed,
.lock_door = viocd_lock_door, .lock_door = viocd_lock_door,
.generic_packet = viocd_packet, .generic_packet = viocd_packet,
.capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM
}; };
static int __init find_capability(const char *type) static int __init find_capability(const char *type)
......
...@@ -2470,52 +2470,6 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi, ...@@ -2470,52 +2470,6 @@ static int ide_cdrom_packet(struct cdrom_device_info *cdi,
return cgc->stat; return cgc->stat;
} }
static
int ide_cdrom_dev_ioctl (struct cdrom_device_info *cdi,
unsigned int cmd, unsigned long arg)
{
struct packet_command cgc;
char buffer[16];
int stat;
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
/* These will be moved into the Uniform layer shortly... */
switch (cmd) {
case CDROMSETSPINDOWN: {
char spindown;
if (copy_from_user(&spindown, (void __user *) arg, sizeof(char)))
return -EFAULT;
if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
return stat;
buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
return cdrom_mode_select(cdi, &cgc);
}
case CDROMGETSPINDOWN: {
char spindown;
if ((stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0)))
return stat;
spindown = buffer[11] & 0x0f;
if (copy_to_user((void __user *) arg, &spindown, sizeof (char)))
return -EFAULT;
return 0;
}
default:
return -EINVAL;
}
}
static static
int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi, int ide_cdrom_audio_ioctl (struct cdrom_device_info *cdi,
unsigned int cmd, void *arg) unsigned int cmd, void *arg)
...@@ -2852,12 +2806,11 @@ static struct cdrom_device_ops ide_cdrom_dops = { ...@@ -2852,12 +2806,11 @@ static struct cdrom_device_ops ide_cdrom_dops = {
.get_mcn = ide_cdrom_get_mcn, .get_mcn = ide_cdrom_get_mcn,
.reset = ide_cdrom_reset, .reset = ide_cdrom_reset,
.audio_ioctl = ide_cdrom_audio_ioctl, .audio_ioctl = ide_cdrom_audio_ioctl,
.dev_ioctl = ide_cdrom_dev_ioctl,
.capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_SELECT_SPEED | CDC_SELECT_DISC |
CDC_MULTI_SESSION | CDC_MCN | CDC_MULTI_SESSION | CDC_MCN |
CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET |
CDC_IOCTLS | CDC_DRIVE_STATUS | CDC_CD_R | CDC_DRIVE_STATUS | CDC_CD_R |
CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM | CDC_CD_RW | CDC_DVD | CDC_DVD_R| CDC_DVD_RAM |
CDC_GENERIC_PACKET | CDC_MO_DRIVE | CDC_MRW | CDC_GENERIC_PACKET | CDC_MO_DRIVE | CDC_MRW |
CDC_MRW_W | CDC_RAM, CDC_MRW_W | CDC_RAM,
...@@ -3367,6 +3320,45 @@ static int idecd_release(struct inode * inode, struct file * file) ...@@ -3367,6 +3320,45 @@ static int idecd_release(struct inode * inode, struct file * file)
return 0; return 0;
} }
static int idecd_set_spindown(struct cdrom_device_info *cdi, unsigned long arg)
{
struct packet_command cgc;
char buffer[16];
int stat;
char spindown;
if (copy_from_user(&spindown, (void __user *)arg, sizeof(char)))
return -EFAULT;
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
if (stat)
return stat;
buffer[11] = (buffer[11] & 0xf0) | (spindown & 0x0f);
return cdrom_mode_select(cdi, &cgc);
}
static int idecd_get_spindown(struct cdrom_device_info *cdi, unsigned long arg)
{
struct packet_command cgc;
char buffer[16];
int stat;
char spindown;
init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_UNKNOWN);
stat = cdrom_mode_sense(cdi, &cgc, GPMODE_CDROM_PAGE, 0);
if (stat)
return stat;
spindown = buffer[11] & 0x0f;
if (copy_to_user((void __user *)arg, &spindown, sizeof (char)))
return -EFAULT;
return 0;
}
static int idecd_ioctl (struct inode *inode, struct file *file, static int idecd_ioctl (struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
...@@ -3374,6 +3366,15 @@ static int idecd_ioctl (struct inode *inode, struct file *file, ...@@ -3374,6 +3366,15 @@ static int idecd_ioctl (struct inode *inode, struct file *file,
struct cdrom_info *info = ide_cd_g(bdev->bd_disk); struct cdrom_info *info = ide_cd_g(bdev->bd_disk);
int err; int err;
switch (cmd) {
case CDROMSETSPINDOWN:
return idecd_set_spindown(&info->devinfo, arg);
case CDROMGETSPINDOWN:
return idecd_get_spindown(&info->devinfo, arg);
default:
break;
}
err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg); err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg);
if (err == -EINVAL) if (err == -EINVAL)
err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg); err = cdrom_ioctl(file, &info->devinfo, inode, cmd, arg);
......
...@@ -71,7 +71,7 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR); ...@@ -71,7 +71,7 @@ MODULE_ALIAS_BLOCKDEV_MAJOR(SCSI_CDROM_MAJOR);
#define SR_CAPABILITIES \ #define SR_CAPABILITIES \
(CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK|CDC_SELECT_SPEED| \ (CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK|CDC_SELECT_SPEED| \
CDC_SELECT_DISC|CDC_MULTI_SESSION|CDC_MCN|CDC_MEDIA_CHANGED| \ CDC_SELECT_DISC|CDC_MULTI_SESSION|CDC_MCN|CDC_MEDIA_CHANGED| \
CDC_PLAY_AUDIO|CDC_RESET|CDC_IOCTLS|CDC_DRIVE_STATUS| \ CDC_PLAY_AUDIO|CDC_RESET|CDC_DRIVE_STATUS| \
CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \ CDC_CD_R|CDC_CD_RW|CDC_DVD|CDC_DVD_R|CDC_DVD_RAM|CDC_GENERIC_PACKET| \
CDC_MRW|CDC_MRW_W|CDC_RAM) CDC_MRW|CDC_MRW_W|CDC_RAM)
...@@ -118,7 +118,6 @@ static struct cdrom_device_ops sr_dops = { ...@@ -118,7 +118,6 @@ static struct cdrom_device_ops sr_dops = {
.get_mcn = sr_get_mcn, .get_mcn = sr_get_mcn,
.reset = sr_reset, .reset = sr_reset,
.audio_ioctl = sr_audio_ioctl, .audio_ioctl = sr_audio_ioctl,
.dev_ioctl = sr_dev_ioctl,
.capability = SR_CAPABILITIES, .capability = SR_CAPABILITIES,
.generic_packet = sr_packet, .generic_packet = sr_packet,
}; };
...@@ -456,6 +455,8 @@ static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd, ...@@ -456,6 +455,8 @@ static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
{ {
struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk); struct scsi_cd *cd = scsi_cd(inode->i_bdev->bd_disk);
struct scsi_device *sdev = cd->device; struct scsi_device *sdev = cd->device;
void __user *argp = (void __user *)arg;
int ret;
/* /*
* Send SCSI addressing ioctls directly to mid level, send other * Send SCSI addressing ioctls directly to mid level, send other
...@@ -464,9 +465,23 @@ static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd, ...@@ -464,9 +465,23 @@ static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd,
switch (cmd) { switch (cmd) {
case SCSI_IOCTL_GET_IDLUN: case SCSI_IOCTL_GET_IDLUN:
case SCSI_IOCTL_GET_BUS_NUMBER: case SCSI_IOCTL_GET_BUS_NUMBER:
return scsi_ioctl(sdev, cmd, (void __user *)arg); return scsi_ioctl(sdev, cmd, argp);
} }
return cdrom_ioctl(file, &cd->cdi, inode, cmd, arg);
ret = cdrom_ioctl(file, &cd->cdi, inode, cmd, arg);
if (ret != ENOSYS)
return ret;
/*
* ENODEV means that we didn't recognise the ioctl, or that we
* cannot execute it in the current device state. In either
* case fall through to scsi_ioctl, which will return ENDOEV again
* if it doesn't recognise the ioctl
*/
ret = scsi_nonblockable_ioctl(sdev, cmd, argp, NULL);
if (ret != -ENODEV)
return ret;
return scsi_ioctl(sdev, cmd, argp);
} }
static int sr_block_media_changed(struct gendisk *disk) static int sr_block_media_changed(struct gendisk *disk)
......
...@@ -55,7 +55,6 @@ int sr_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *); ...@@ -55,7 +55,6 @@ int sr_get_mcn(struct cdrom_device_info *, struct cdrom_mcn *);
int sr_reset(struct cdrom_device_info *); int sr_reset(struct cdrom_device_info *);
int sr_select_speed(struct cdrom_device_info *cdi, int speed); int sr_select_speed(struct cdrom_device_info *cdi, int speed);
int sr_audio_ioctl(struct cdrom_device_info *, unsigned int, void *); int sr_audio_ioctl(struct cdrom_device_info *, unsigned int, void *);
int sr_dev_ioctl(struct cdrom_device_info *, unsigned int, unsigned long);
int sr_is_xa(Scsi_CD *); int sr_is_xa(Scsi_CD *);
......
...@@ -562,22 +562,3 @@ int sr_is_xa(Scsi_CD *cd) ...@@ -562,22 +562,3 @@ int sr_is_xa(Scsi_CD *cd)
#endif #endif
return is_xa; return is_xa;
} }
int sr_dev_ioctl(struct cdrom_device_info *cdi,
unsigned int cmd, unsigned long arg)
{
Scsi_CD *cd = cdi->handle;
int ret;
ret = scsi_nonblockable_ioctl(cd->device, cmd,
(void __user *)arg, NULL);
/*
* ENODEV means that we didn't recognise the ioctl, or that we
* cannot execute it in the current device state. In either
* case fall through to scsi_ioctl, which will return ENDOEV again
* if it doesn't recognise the ioctl
*/
if (ret != -ENODEV)
return ret;
return scsi_ioctl(cd->device, cmd, (void __user *)arg);
}
...@@ -378,7 +378,6 @@ struct cdrom_generic_command ...@@ -378,7 +378,6 @@ struct cdrom_generic_command
#define CDC_MEDIA_CHANGED 0x80 /* media changed */ #define CDC_MEDIA_CHANGED 0x80 /* media changed */
#define CDC_PLAY_AUDIO 0x100 /* audio functions */ #define CDC_PLAY_AUDIO 0x100 /* audio functions */
#define CDC_RESET 0x200 /* hard reset device */ #define CDC_RESET 0x200 /* hard reset device */
#define CDC_IOCTLS 0x400 /* driver has non-standard ioctls */
#define CDC_DRIVE_STATUS 0x800 /* driver implements drive status */ #define CDC_DRIVE_STATUS 0x800 /* driver implements drive status */
#define CDC_GENERIC_PACKET 0x1000 /* driver implements generic packets */ #define CDC_GENERIC_PACKET 0x1000 /* driver implements generic packets */
#define CDC_CD_R 0x2000 /* drive is a CD-R */ #define CDC_CD_R 0x2000 /* drive is a CD-R */
...@@ -974,9 +973,7 @@ struct cdrom_device_ops { ...@@ -974,9 +973,7 @@ struct cdrom_device_ops {
int (*reset) (struct cdrom_device_info *); int (*reset) (struct cdrom_device_info *);
/* play stuff */ /* play stuff */
int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *); int (*audio_ioctl) (struct cdrom_device_info *,unsigned int, void *);
/* dev-specific */
int (*dev_ioctl) (struct cdrom_device_info *,
unsigned int, unsigned long);
/* driver specifications */ /* driver specifications */
const int capability; /* capability flags */ const int capability; /* capability flags */
int n_minors; /* number of active minor devices */ int n_minors; /* number of active minor devices */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册