Commit 6a2900b6 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by 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: default avatarChristoph Hellwig <hch@lst.de>
Acked-by: default avatarJens Axboe <axboe@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 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,484 +4178,163 @@ static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd, ...@@ -4183,484 +4178,163 @@ 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");
/* 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 #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); if (current_drive->audio_state==audio_playing)
cc_ModeSense(); {
current_drive->mode=READ_M1; 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); RETURN_UP(0);
case CDROMREADMODE2: /* not usable at the moment */ case CDROMPLAYTRKIND: /* Play a track. This currently ignores index. */
msg(DBG_IOC,"ioctl: CDROMREADMODE2 requested.\n"); msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND 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; 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); RETURN_UP(0);
case CDROMAUDIOBUFSIZ: /* configure the audio buffer size */ case CDROMREADTOCHDR: /* Read the table of contents header */
msg(DBG_IOC,"ioctl: CDROMAUDIOBUFSIZ entered.\n"); msg(DBG_IOC,"ioctl: CDROMREADTOCHDR entered.\n");
if (current_drive->sbp_audsiz>0) tochdr.cdth_trk0=current_drive->n_first_track;
vfree(current_drive->aud_buf); tochdr.cdth_trk1=current_drive->n_last_track;
current_drive->aud_buf=NULL; memcpy((void *) arg, &tochdr, sizeof(struct cdrom_tochdr));
current_drive->sbp_audsiz=arg; RETURN_UP(0);
if (current_drive->sbp_audsiz>16) case CDROMREADTOCENTRY: /* Read an entry in the table of contents */
{ msg(DBG_IOC,"ioctl: CDROMREADTOCENTRY entered.\n");
current_drive->sbp_audsiz = 0; memcpy(&tocentry, (void *) arg, sizeof(struct cdrom_tocentry));
RETURN_UP(current_drive->sbp_audsiz); 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)
if (current_drive->sbp_audsiz>0) 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 */
{ {
current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW); tocentry.cdte_addr.msf.minute=(current_drive->TocBuffer[i].address>>16)&0x00FF;
if (current_drive->aud_buf==NULL) tocentry.cdte_addr.msf.second=(current_drive->TocBuffer[i].address>>8)&0x00FF;
{ tocentry.cdte_addr.msf.frame=current_drive->TocBuffer[i].address&0x00FF;
msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz);
current_drive->sbp_audsiz=0;
}
else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz);
} }
RETURN_UP(current_drive->sbp_audsiz); else if (tocentry.cdte_format==CDROM_LBA) /* blk required */
tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address);
case CDROMREADAUDIO: else RETURN_UP(-EINVAL);
{ /* start of CDROMREADAUDIO */ memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
int i=0, j=0, frame, block=0; RETURN_UP(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 CDROMSTOP: /* Spin down the drive */
if (fam0_drive) RETURN_UP(-EINVAL); msg(DBG_IOC,"ioctl: CDROMSTOP 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); i=cc_Pause_Resume(1);
if (copy_from_user(&read_audio, (void __user *)arg, current_drive->audio_state=0;
sizeof(struct cdrom_read_audio))) #if 0
RETURN_UP(-EFAULT); cc_DriveReset();
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;
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;
}
msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
if (fam0L_drive)
{
flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
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)
{
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)
{
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 */
{
}
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++)
{
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 */
tocentry.cdte_addr.lba=msf2blk(current_drive->TocBuffer[i].address);
else RETURN_UP(-EINVAL);
memcpy((void *) arg, &tocentry, sizeof(struct cdrom_tocentry));
RETURN_UP(0);
case CDROMSTOP: /* Spin down the drive */
msg(DBG_IOC,"ioctl: CDROMSTOP entered.\n");
#ifdef SAFE_MIXED
if (current_drive->has_data>1) RETURN_UP(-EBUSY);
#endif /* SAFE_MIXED */
i=cc_Pause_Resume(1);
current_drive->audio_state=0;
#if 0
cc_DriveReset();
#endif #endif
RETURN_UP(i); RETURN_UP(i);
case CDROMSTART: /* Spin up the drive */ case CDROMSTART: /* Spin up the drive */
msg(DBG_IOC,"ioctl: CDROMSTART entered.\n"); msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
cc_SpinUp(); cc_SpinUp();
current_drive->audio_state=0; current_drive->audio_state=0;
RETURN_UP(0); RETURN_UP(0);
case CDROMVOLCTRL: /* Volume control */ case CDROMVOLCTRL: /* Volume control */
msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n"); msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
memcpy(&volctrl,(char *) arg,sizeof(volctrl)); memcpy(&volctrl,(char *) arg,sizeof(volctrl));
...@@ -4670,7 +4344,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, ...@@ -4670,7 +4344,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
current_drive->vol_ctrl1=volctrl.channel1; current_drive->vol_ctrl1=volctrl.channel1;
i=cc_SetVolume(); i=cc_SetVolume();
RETURN_UP(0); RETURN_UP(0);
case CDROMVOLREAD: /* read Volume settings from drive */ case CDROMVOLREAD: /* read Volume settings from drive */
msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n"); msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
st=cc_GetVolume(); st=cc_GetVolume();
...@@ -4694,7 +4368,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, ...@@ -4694,7 +4368,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
if (i<0) { if (i<0) {
j=cc_ReadError(); /* clear out error status from drive */ j=cc_ReadError(); /* clear out error status from drive */
current_drive->audio_state=CDROM_AUDIO_NO_STATUS; current_drive->audio_state=CDROM_AUDIO_NO_STATUS;
/* get and set the disk state here, /* get and set the disk state here,
probably not the right place, but who cares! probably not the right place, but who cares!
It makes it work properly! --AJK */ It makes it work properly! --AJK */
if (current_drive->CD_changed==0xFF) { if (current_drive->CD_changed==0xFF) {
...@@ -4715,8 +4389,8 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, ...@@ -4715,8 +4389,8 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
} }
} }
memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl)); memcpy(&SC, (void *) arg, sizeof(struct cdrom_subchnl));
/* /*
This virtual crap is very bogus! This virtual crap is very bogus!
It doesn't detect when the cd is done playing audio! It doesn't detect when the cd is done playing audio!
Lets do this right with proper hardware register reading! Lets do this right with proper hardware register reading!
*/ */
...@@ -4775,7 +4449,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, ...@@ -4775,7 +4449,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
SC.cdsc_trk,SC.cdsc_ind, SC.cdsc_trk,SC.cdsc_ind,
SC.cdsc_absaddr,SC.cdsc_reladdr); SC.cdsc_absaddr,SC.cdsc_reladdr);
RETURN_UP(0); RETURN_UP(0);
default: default:
msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd); msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
RETURN_UP(-EINVAL); RETURN_UP(-EINVAL);
...@@ -4788,7 +4462,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd, ...@@ -4788,7 +4462,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
static void sbp_transfer(struct request *req) static void sbp_transfer(struct request *req)
{ {
long offs; long offs;
while ( (req->nr_sectors > 0) && while ( (req->nr_sectors > 0) &&
(req->sector/4 >= current_drive->sbp_first_frame) && (req->sector/4 >= current_drive->sbp_first_frame) &&
(req->sector/4 <= current_drive->sbp_last_frame) ) (req->sector/4 <= current_drive->sbp_last_frame) )
...@@ -4807,11 +4481,11 @@ static void sbp_transfer(struct request *req) ...@@ -4807,11 +4481,11 @@ static void sbp_transfer(struct request *req)
* *
* This is a kludge so we don't need to modify end_request. * This is a kludge so we don't need to modify end_request.
* We put the req we take out after INIT_REQUEST in the requests list, * We put the req we take out after INIT_REQUEST in the requests list,
* so that end_request will discard it. * so that end_request will discard it.
* *
* The bug could be present in other block devices, perhaps we * The bug could be present in other block devices, perhaps we
* should modify INIT_REQUEST and end_request instead, and * should modify INIT_REQUEST and end_request instead, and
* change every block device.. * change every block device..
* *
* Could be a race here?? Could e.g. a timer interrupt schedule() us? * Could be a race here?? Could e.g. a timer interrupt schedule() us?
* If so, we should copy end_request here, and do it right.. (or * If so, we should copy end_request here, and do it right.. (or
...@@ -4831,546 +4505,865 @@ static void sbp_transfer(struct request *req) ...@@ -4831,546 +4505,865 @@ static void sbp_transfer(struct request *req)
/*==========================================================================*/ /*==========================================================================*/
/* /*
* I/O request routine, called from Linux kernel. * I/O request routine, called from Linux kernel.
*/
static void do_sbpcd_request(request_queue_t * q)
{
u_int block;
u_int nsect;
int status_tries, data_tries;
struct request *req;
struct sbpcd_drive *p;
#ifdef DEBUG_GTL
static int xx_nr=0;
int xnr;
#endif
request_loop:
#ifdef DEBUG_GTL
xnr=++xx_nr;
req = elv_next_request(q);
if (!req)
{
printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n",
xnr, current->pid, jiffies);
printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n",
xnr, jiffies);
return;
}
printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n",
xnr, req, req->sector, req->nr_sectors, current->pid, jiffies);
#endif
req = elv_next_request(q); /* take out our request so no other */
if (!req)
return;
if (req -> sector == -1)
end_request(req, 0);
spin_unlock_irq(q->queue_lock);
down(&ioctl_read_sem);
if (rq_data_dir(elv_next_request(q)) != READ)
{
msg(DBG_INF, "bad cmd %d\n", req->cmd[0]);
goto err_done;
}
p = req->rq_disk->private_data;
#if OLD_BUSY
while (busy_audio) sbp_sleep(HZ); /* wait a bit */
busy_data=1;
#endif /* OLD_BUSY */
if (p->audio_state==audio_playing) goto err_done;
if (p != current_drive)
switch_drive(p);
block = req->sector; /* always numbered as 512-byte-pieces */
nsect = req->nr_sectors; /* always counted as 512-byte-pieces */
msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect);
#if 0
msg(DBG_MUL,"read LBA %d\n", block/4);
#endif
sbp_transfer(req);
/* if we satisfied the request from the buffer, we're done. */
if (req->nr_sectors == 0)
{
#ifdef DEBUG_GTL
printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n",
xnr, req, req->sector, req->nr_sectors, jiffies);
#endif
up(&ioctl_read_sem);
spin_lock_irq(q->queue_lock);
end_request(req, 1);
goto request_loop;
}
#ifdef FUTURE
i=prepare(0,0); /* at moment not really a hassle check, but ... */
if (i!=0)
msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i);
#endif /* FUTURE */
if (!st_spinning) cc_SpinUp();
for (data_tries=n_retries; data_tries > 0; data_tries--)
{
for (status_tries=3; status_tries > 0; status_tries--)
{
flags_cmd_out |= f_respo3;
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_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__);
break;
}
sbp_read_cmd(req);
sbp_sleep(0);
if (sbp_data(req) != 0)
{
#ifdef SAFE_MIXED
current_drive->has_data=2; /* is really a data disk */
#endif /* SAFE_MIXED */
#ifdef DEBUG_GTL
printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n",
xnr, req, req->sector, req->nr_sectors, jiffies);
#endif
up(&ioctl_read_sem);
spin_lock_irq(q->queue_lock);
end_request(req, 1);
goto request_loop;
}
}
err_done:
#if OLD_BUSY
busy_data=0;
#endif /* OLD_BUSY */
#ifdef DEBUG_GTL
printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n",
xnr, req, req->sector, req->nr_sectors, jiffies);
#endif
up(&ioctl_read_sem);
sbp_sleep(0); /* wait a bit, try again */
spin_lock_irq(q->queue_lock);
end_request(req, 0);
goto request_loop;
}
/*==========================================================================*/
/*
* build and send the READ command.
*/
static void sbp_read_cmd(struct request *req)
{
#undef OLD
int i;
int block;
current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */
current_drive->sbp_current = 0;
block=req->sector/4;
if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm)
current_drive->sbp_read_frames = current_drive->sbp_bufsiz;
else
{
current_drive->sbp_read_frames=current_drive->CDsize_frm-block;
/* avoid reading past end of data */
if (current_drive->sbp_read_frames < 1)
{
msg(DBG_INF,"requested frame %d, CD size %d ???\n",
block, current_drive->CDsize_frm);
current_drive->sbp_read_frames=1;
}
}
flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
clr_cmdbuf();
if (famV_drive)
{
drvcmd[0]=CMDV_READ;
lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
bin2bcdx(&drvcmd[1]);
bin2bcdx(&drvcmd[2]);
bin2bcdx(&drvcmd[3]);
drvcmd[4]=current_drive->sbp_read_frames>>8;
drvcmd[5]=current_drive->sbp_read_frames&0xff;
drvcmd[6]=0x02; /* flag "msf-bcd" */
}
else if (fam0L_drive)
{
flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
if (current_drive->xa_byte==0x20)
{
cmd_type=READ_M2;
drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
drvcmd[1]=(block>>16)&0x0ff;
drvcmd[2]=(block>>8)&0x0ff;
drvcmd[3]=block&0x0ff;
drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
}
else
{
drvcmd[0]=CMD0_READ; /* "read frames", old drives */
if (current_drive->drv_type>=drv_201)
{
lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
bin2bcdx(&drvcmd[1]);
bin2bcdx(&drvcmd[2]);
bin2bcdx(&drvcmd[3]);
}
else
{
drvcmd[1]=(block>>16)&0x0ff;
drvcmd[2]=(block>>8)&0x0ff;
drvcmd[3]=block&0x0ff;
}
drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */
}
}
else if (fam1_drive)
{
drvcmd[0]=CMD1_READ;
lba2msf(block,&drvcmd[1]); /* msf-bin format required */
drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff;
drvcmd[6]=current_drive->sbp_read_frames&0x0ff;
}
else if (fam2_drive)
{
drvcmd[0]=CMD2_READ;
lba2msf(block,&drvcmd[1]); /* msf-bin format required */
drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
drvcmd[6]=0x02;
}
else if (famT_drive)
{
drvcmd[0]=CMDT_READ;
drvcmd[2]=(block>>24)&0x0ff;
drvcmd[3]=(block>>16)&0x0ff;
drvcmd[4]=(block>>8)&0x0ff;
drvcmd[5]=block&0x0ff;
drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff;
drvcmd[8]=current_drive->sbp_read_frames&0x0ff;
}
flags_cmd_out=f_putcmd;
response_count=0;
i=cmd_out();
if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i);
return;
}
/*==========================================================================*/
/*
* Check the completion of the read-data command. On success, read
* the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer.
*/ */
static void do_sbpcd_request(request_queue_t * q) static int sbp_data(struct request *req)
{ {
u_int block; int i=0, j=0, l, frame;
u_int nsect; u_int try=0;
int status_tries, data_tries; u_long timeout;
struct request *req; u_char *p;
struct sbpcd_drive *p; u_int data_tries = 0;
#ifdef DEBUG_GTL u_int data_waits = 0;
static int xx_nr=0; u_int data_retrying = 0;
int xnr; int error_flag;
#endif int xa_count;
int max_latency;
request_loop: int success;
#ifdef DEBUG_GTL int wait;
xnr=++xx_nr; int duration;
req = elv_next_request(q);
if (!req)
{
printk( "do_sbpcd_request[%di](NULL), Pid:%d, Time:%li\n",
xnr, current->pid, jiffies);
printk( "do_sbpcd_request[%do](NULL) end 0 (null), Time:%li\n",
xnr, jiffies);
return;
}
printk(" do_sbpcd_request[%di](%p:%ld+%ld), Pid:%d, Time:%li\n", error_flag=0;
xnr, req, req->sector, req->nr_sectors, current->pid, jiffies); success=0;
#if LONG_TIMING
max_latency=9*HZ;
#else
if (current_drive->f_multisession) max_latency=15*HZ;
else max_latency=5*HZ;
#endif #endif
duration=jiffies;
for (frame=0;frame<current_drive->sbp_read_frames&&!error_flag; frame++)
{
SBPCD_CLI;
req = elv_next_request(q); /* take out our request so no other */ del_timer(&data_timer);
if (!req) data_timer.expires=jiffies+max_latency;
return; 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 (req -> sector == -1) if (timed_out_data)
end_request(req, 0); {
spin_unlock_irq(q->queue_lock); 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;
down(&ioctl_read_sem); msg(DBG_000, "sbp_data: beginning to read.\n");
if (rq_data_dir(elv_next_request(q)) != READ) p = current_drive->sbp_buf + frame * CD_FRAMESIZE;
{ if (sbpro_type==1) OUT(CDo_sel_i_d,1);
msg(DBG_INF, "bad cmd %d\n", req->cmd[0]); if (cmd_type==READ_M2) {
goto err_done; 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;
}
} }
p = req->rq_disk->private_data; duration=jiffies-duration;
#if OLD_BUSY msg(DBG_TEA,"time to read %d frames: %d jiffies .\n",frame,duration);
while (busy_audio) sbp_sleep(HZ); /* wait a bit */ if (famT_drive)
busy_data=1; {
#endif /* OLD_BUSY */ wait=8;
do
if (p->audio_state==audio_playing) goto err_done; {
if (p != current_drive) if (teac==2)
switch_drive(p); {
if ((i=CDi_stat_loop_T()) == -1) break;
block = req->sector; /* always numbered as 512-byte-pieces */ }
nsect = req->nr_sectors; /* always counted as 512-byte-pieces */ else
{
msg(DBG_BSZ,"read sector %d (%d sectors)\n", block, nsect); 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 #if 0
msg(DBG_MUL,"read LBA %d\n", block/4); msg(DBG_TEA, "============= waiting for result=================.\n");
sbp_sleep(1);
#endif #endif
}
sbp_transfer(req); }
/* if we satisfied the request from the buffer, we're done. */ while (wait--);
if (req->nr_sectors == 0) }
if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
{ {
#ifdef DEBUG_GTL msg(DBG_TEA, "================error flag: %d=================.\n", error_flag);
printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 2, Time:%li\n", msg(DBG_INF,"sbp_data: read aborted by drive.\n");
xnr, req, req->sector, req->nr_sectors, jiffies); #if 1
i=cc_DriveReset(); /* ugly fix to prevent a hang */
#else
i=cc_ReadError();
#endif #endif
up(&ioctl_read_sem); return (0);
spin_lock_irq(q->queue_lock);
end_request(req, 1);
goto request_loop;
} }
#ifdef FUTURE
i=prepare(0,0); /* at moment not really a hassle check, but ... */
if (i!=0)
msg(DBG_INF,"\"prepare\" tells error %d -- ignored\n", i);
#endif /* FUTURE */
if (!st_spinning) cc_SpinUp();
for (data_tries=n_retries; data_tries > 0; data_tries--) if (fam0LV_drive)
{ {
for (status_tries=3; status_tries > 0; status_tries--) SBPCD_CLI;
i=maxtim_data;
for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
{ {
flags_cmd_out |= f_respo3; for ( ;i!=0;i--)
cc_ReadStatus(); {
if (sbp_status() != 0) break; j=inb(CDi_status);
if (st_check) cc_ReadError(); if (!(j&s_not_data_ready)) break;
sbp_sleep(1); /* wait a bit, try again */ 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 (status_tries == 0) if (i==0) msg(DBG_INF,"status timeout after READ.\n");
if (!(j&s_attention))
{ {
msg(DBG_INF,"sbp_status: failed after 3 tries in line %d\n", __LINE__); msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n");
break; i=cc_DriveReset(); /* ugly fix to prevent a hang */
SBPCD_STI;
return (0);
} }
SBPCD_STI;
sbp_read_cmd(req); }
sbp_sleep(0);
if (sbp_data(req) != 0) #if 0
if (!success)
#endif
do
{ {
#ifdef SAFE_MIXED if (fam0LV_drive) cc_ReadStatus();
current_drive->has_data=2; /* is really a data disk */ #if 1
#endif /* SAFE_MIXED */ if (famT_drive) msg(DBG_TEA, "================before ResponseStatus=================.\n", i);
#ifdef DEBUG_GTL
printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 3, Time:%li\n",
xnr, req, req->sector, req->nr_sectors, jiffies);
#endif #endif
up(&ioctl_read_sem); i=ResponseStatus(); /* builds status_bits, returns orig. status (old) or faked p_success (new) */
spin_lock_irq(q->queue_lock); #if 1
end_request(req, 1); if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i);
goto request_loop; #endif
if (i<0)
{
msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits);
return (0);
}
} }
while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success)));
if (st_check)
{
i=cc_ReadError();
msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i);
return (0);
}
if (fatal_err)
{
fatal_err=0;
current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */
current_drive->sbp_current = 0;
msg(DBG_INF,"sbp_data: fatal_err - retrying.\n");
return (0);
} }
err_done: current_drive->sbp_first_frame = req -> sector / 4;
#if OLD_BUSY current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1;
busy_data=0; sbp_transfer(req);
#endif /* OLD_BUSY */ return (1);
#ifdef DEBUG_GTL
printk(" do_sbpcd_request[%do](%p:%ld+%ld) end 4 (error), Time:%li\n",
xnr, req, req->sector, req->nr_sectors, jiffies);
#endif
up(&ioctl_read_sem);
sbp_sleep(0); /* wait a bit, try again */
spin_lock_irq(q->queue_lock);
end_request(req, 0);
goto request_loop;
} }
/*==========================================================================*/ /*==========================================================================*/
/*
* build and send the READ command. static int sbpcd_block_open(struct inode *inode, struct file *file)
*/
static void sbp_read_cmd(struct request *req)
{ {
#undef OLD struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data;
return cdrom_open(p->sbpcd_infop, inode, file);
}
int i; static int sbpcd_block_release(struct inode *inode, struct file *file)
int block; {
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 */
}
down(&ioctl_read_sem);
if (p != current_drive)
switch_drive(p);
current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ msg(DBG_IO2,"ioctl: device %s, request %04X\n",cdi->name,cmd);
current_drive->sbp_current = 0; switch (cmd) /* Sun-compatible */
block=req->sector/4;
if (block+current_drive->sbp_bufsiz <= current_drive->CDsize_frm)
current_drive->sbp_read_frames = current_drive->sbp_bufsiz;
else
{ {
current_drive->sbp_read_frames=current_drive->CDsize_frm-block; case DDIOCSDBG: /* DDI Debug */
/* avoid reading past end of data */ if (!capable(CAP_SYS_ADMIN)) RETURN_UP(-EPERM);
if (current_drive->sbp_read_frames < 1) 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)
{ {
msg(DBG_INF,"requested frame %d, CD size %d ???\n", current_drive->sbp_audsiz = 0;
block, current_drive->CDsize_frm); RETURN_UP(current_drive->sbp_audsiz);
current_drive->sbp_read_frames=1;
} }
}
flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check; if (current_drive->sbp_audsiz>0)
clr_cmdbuf();
if (famV_drive)
{
drvcmd[0]=CMDV_READ;
lba2msf(block,&drvcmd[1]); /* msf-bcd format required */
bin2bcdx(&drvcmd[1]);
bin2bcdx(&drvcmd[2]);
bin2bcdx(&drvcmd[3]);
drvcmd[4]=current_drive->sbp_read_frames>>8;
drvcmd[5]=current_drive->sbp_read_frames&0xff;
drvcmd[6]=0x02; /* flag "msf-bcd" */
}
else if (fam0L_drive)
{
flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
if (current_drive->xa_byte==0x20)
{ {
cmd_type=READ_M2; current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW);
drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */ if (current_drive->aud_buf==NULL)
drvcmd[1]=(block>>16)&0x0ff; {
drvcmd[2]=(block>>8)&0x0ff; msg(DBG_INF,"audio buffer (%d frames) not available.\n",current_drive->sbp_audsiz);
drvcmd[3]=block&0x0ff; current_drive->sbp_audsiz=0;
drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; }
drvcmd[5]=current_drive->sbp_read_frames&0x0ff; else msg(DBG_INF,"audio buffer size: %d frames.\n",current_drive->sbp_audsiz);
} }
else 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--)
{ {
drvcmd[0]=CMD0_READ; /* "read frames", old drives */ msg(DBG_AUD,"data_tries=%d ...\n", data_tries);
if (current_drive->drv_type>=drv_201) current_drive->mode=READ_AU;
cc_ModeSelect(CD_FRAMESIZE_RAW);
cc_ModeSense();
for (status_tries=3; status_tries > 0; status_tries--)
{ {
lba2msf(block,&drvcmd[1]); /* msf-bcd format required */ flags_cmd_out |= f_respo3;
bin2bcdx(&drvcmd[1]); cc_ReadStatus();
bin2bcdx(&drvcmd[2]); if (sbp_status() != 0) break;
bin2bcdx(&drvcmd[3]); if (st_check) cc_ReadError();
sbp_sleep(1); /* wait a bit, try again */
} }
else if (status_tries == 0)
{ {
drvcmd[1]=(block>>16)&0x0ff; msg(DBG_AUD,"read_audio: sbp_status: failed after 3 tries in line %d.\n", __LINE__);
drvcmd[2]=(block>>8)&0x0ff; continue;
drvcmd[3]=block&0x0ff;
} }
drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff; msg(DBG_AUD,"read_audio: sbp_status: ok.\n");
drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
drvcmd[6]=(current_drive->drv_type<drv_201)?0:2; /* flag "lba or msf-bcd format" */ flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
} if (fam0L_drive)
}
else if (fam1_drive)
{
drvcmd[0]=CMD1_READ;
lba2msf(block,&drvcmd[1]); /* msf-bin format required */
drvcmd[5]=(current_drive->sbp_read_frames>>8)&0x0ff;
drvcmd[6]=current_drive->sbp_read_frames&0x0ff;
}
else if (fam2_drive)
{
drvcmd[0]=CMD2_READ;
lba2msf(block,&drvcmd[1]); /* msf-bin format required */
drvcmd[4]=(current_drive->sbp_read_frames>>8)&0x0ff;
drvcmd[5]=current_drive->sbp_read_frames&0x0ff;
drvcmd[6]=0x02;
}
else if (famT_drive)
{
drvcmd[0]=CMDT_READ;
drvcmd[2]=(block>>24)&0x0ff;
drvcmd[3]=(block>>16)&0x0ff;
drvcmd[4]=(block>>8)&0x0ff;
drvcmd[5]=block&0x0ff;
drvcmd[7]=(current_drive->sbp_read_frames>>8)&0x0ff;
drvcmd[8]=current_drive->sbp_read_frames&0x0ff;
}
flags_cmd_out=f_putcmd;
response_count=0;
i=cmd_out();
if (i<0) msg(DBG_INF,"error giving READ command: %0d\n", i);
return;
}
/*==========================================================================*/
/*
* Check the completion of the read-data command. On success, read
* the current_drive->sbp_bufsiz * 2048 bytes of data from the disk into buffer.
*/
static int sbp_data(struct request *req)
{
int i=0, j=0, l, frame;
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 error_flag;
int xa_count;
int max_latency;
int success;
int wait;
int duration;
error_flag=0;
success=0;
#if LONG_TIMING
max_latency=9*HZ;
#else
if (current_drive->f_multisession) max_latency=15*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); flags_cmd_out |= f_lopsta | f_getsta | f_bit1;
if (!(j&s_not_data_ready)) break; cmd_type=READ_M2;
if (!(j&s_not_result_ready)) break; drvcmd[0]=CMD0_READ_XA; /* "read XA frames", old drives */
if (fam0LV_drive) if (j&s_attention) break; 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;
} }
if (!(j&s_not_data_ready)) goto data_ready; else if (fam1_drive)
if (try==0)
{ {
if (data_retrying == 0) data_waits++; drvcmd[0]=CMD1_READ; /* "read frames", new drives */
data_retrying = 1; lba2msf(block,&drvcmd[1]); /* msf-bin format required */
msg(DBG_000,"sbp_data: CDi_status loop: sleeping.\n"); drvcmd[4]=0;
sbp_sleep(1); drvcmd[5]=0;
try = 1; drvcmd[6]=read_audio.nframes; /* # of frames */
} }
} else if (fam2_drive)
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); drvcmd[0]=CMD2_READ_XA2;
j=0; lba2msf(block,&drvcmd[1]); /* msf-bin format required */
do drvcmd[4]=0;
drvcmd[5]=read_audio.nframes; /* # of frames */
drvcmd[6]=0x11; /* raw mode */
}
else if (famT_drive) /* CD-55A: not tested yet */
{
}
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++)
{
try=maxtim_data;
for (timeout=jiffies+9*HZ; ; )
{ {
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;
}
if (try != 0 || time_after_eq(jiffies, timeout)) break;
if (data_retrying == 0) data_waits++;
data_retrying = 1;
sbp_sleep(1);
try = 1;
} }
while (!(i&s_not_data_ready)); if (try==0)
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); 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 break;
{ }
++recursion; msg(DBG_AUD,"read_audio: before reading data.\n");
if (recursion>1) msg(DBG_TEA,"cmd_out_T READ_ERR recursion (sbp_data): %d !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n",recursion); error_flag=0;
else msg(DBG_TEA,"sbp_data: CMDT_READ_ERR necessary.\n"); p = current_drive->aud_buf;
clr_cmdbuf(); if (sbpro_type==1) OUT(CDo_sel_i_d,1);
drvcmd[0]=CMDT_READ_ERR; if (do_16bit)
j=cmd_out_T(); /* !!! recursive here !!! */ {
--recursion; u_short *p2 = (u_short *) p;
sbp_sleep(1);
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);
} }
while (j<0);
current_drive->error_state=infobuf[2];
current_drive->b3=infobuf[3];
current_drive->b4=infobuf[4];
} }
break; if (sbpro_type==1) OUT(CDo_sel_i_d,0);
data_retrying = 0;
} }
else msg(DBG_AUD,"read_audio: after reading data.\n");
if (error_flag) /* must have been spurious D_RDY or (ATTN&&!D_RDY) */
{ {
#if 0 msg(DBG_AUD,"read_audio: read aborted by drive\n");
msg(DBG_TEA, "============= waiting for result=================.\n"); #if 0000
sbp_sleep(1); i=cc_DriveReset(); /* ugly fix to prevent a hang */
#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 #else
i=cc_ReadError(); i=cc_ReadError();
#endif #endif
return (0); continue;
} }
if (fam0L_drive)
if (fam0LV_drive)
{
SBPCD_CLI;
i=maxtim_data;
for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
{
for ( ;i!=0;i--)
{ {
j=inb(CDi_status); i=maxtim_data;
if (!(j&s_not_data_ready)) break; for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
if (!(j&s_not_result_ready)) break; {
if (j&s_attention) break; 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;
}
} }
if (i != 0 || time_after_eq(jiffies, timeout)) break; do
sbp_sleep(0);
i = 1;
}
if (i==0) msg(DBG_INF,"status timeout after READ.\n");
if (!(j&s_attention))
{
msg(DBG_INF,"sbp_data: timeout waiting DRV_ATTN - retrying.\n");
i=cc_DriveReset(); /* ugly fix to prevent a hang */
SBPCD_STI;
return (0);
}
SBPCD_STI;
}
#if 0
if (!success)
#endif
do
{
if (fam0LV_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) */
#if 1
if (famT_drive) msg(DBG_TEA, "================ResponseStatus: %d=================.\n", i);
#endif
if (i<0)
{ {
msg(DBG_INF,"bad cc_ReadStatus after read: %02X\n", current_drive->status_bits); if (fam0L_drive) cc_ReadStatus();
return (0); 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;
} }
while ((fam0LV_drive)&&(!st_check)&&(!(i&p_success))); cc_ModeSelect(CD_FRAMESIZE);
if (st_check) cc_ModeSense();
{ current_drive->mode=READ_M1;
i=cc_ReadError(); #if OLD_BUSY
msg(DBG_INF,"cc_ReadError was necessary after read: %d\n",i); busy_audio=0;
return (0); #endif /* OLD_BUSY */
} if (data_tries == 0)
if (fatal_err) {
{ msg(DBG_AUD,"read_audio: failed after 5 tries in line %d.\n", __LINE__);
fatal_err=0; RETURN_UP(-EIO);
current_drive->sbp_first_frame=current_drive->sbp_last_frame=-1; /* purge buffer */ }
current_drive->sbp_current = 0; msg(DBG_AUD,"read_audio: successful return.\n");
msg(DBG_INF,"sbp_data: fatal_err - retrying.\n"); RETURN_UP(0);
return (0); } /* end of CDROMREADAUDIO */
}
current_drive->sbp_first_frame = req -> sector / 4;
current_drive->sbp_last_frame = current_drive->sbp_first_frame + current_drive->sbp_read_frames - 1;
sbp_transfer(req);
return (1);
}
/*==========================================================================*/
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, default:
unsigned cmd, unsigned long arg) msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
{ RETURN_UP(-EINVAL);
struct sbpcd_drive *p = inode->i_bdev->bd_disk->private_data; } /* end switch(cmd) */
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,7 +3366,16 @@ static int idecd_ioctl (struct inode *inode, struct file *file, ...@@ -3374,7 +3366,16 @@ 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;
err = generic_ide_ioctl(info->drive, file, bdev, cmd, arg); 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);
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,17 +455,33 @@ static int sr_block_ioctl(struct inode *inode, struct file *file, unsigned cmd, ...@@ -456,17 +455,33 @@ 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
* ioctls to cdrom/block level. * ioctls to cdrom/block level.
*/ */
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%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment