aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cdrom/sbpcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cdrom/sbpcd.c')
-rw-r--r--drivers/cdrom/sbpcd.c720
1 files changed, 359 insertions, 361 deletions
diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c
index 466e9c2974bd..05c9e865ecaf 100644
--- a/drivers/cdrom/sbpcd.c
+++ b/drivers/cdrom/sbpcd.c
@@ -464,8 +464,13 @@ static int sbpcd[] =
static __cacheline_aligned DEFINE_SPINLOCK(sbpcd_lock);
static struct request_queue *sbpcd_queue;
-MODULE_PARM(sbpcd, "2i");
-MODULE_PARM(max_drives, "i");
+/* You can only set the first pair, from old MODULE_PARM code. */
+static int sbpcd_set(const char *val, struct kernel_param *kp)
+{
+ get_options((char *)val, 2, (int *)sbpcd);
+ return 0;
+}
+module_param_call(sbpcd, sbpcd_set, NULL, NULL, 0);
#define NUM_PROBE (sizeof(sbpcd) / sizeof(int))
@@ -553,6 +558,7 @@ static unsigned char msgnum;
static char msgbuf[80];
static int max_drives = MAX_DRIVES;
+module_param(max_drives, int, 0);
#ifndef MODULE
static unsigned char setup_done;
static const char *str_sb_l = "soundblaster";
@@ -4160,332 +4166,6 @@ static int sbpcd_get_last_session(struct cdrom_device_info *cdi, struct cdrom_mu
return 0;
}
-/*==========================================================================*/
-/*==========================================================================*/
-/*
- * ioctl support
- */
-static int sbpcd_dev_ioctl(struct cdrom_device_info *cdi, u_int cmd,
- u_long arg)
-{
- struct sbpcd_drive *p = cdi->handle;
- int i;
-
- 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);
-
- 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);
- }
-
- if (current_drive->sbp_audsiz>0)
- {
- current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW);
- if (current_drive->aud_buf==NULL)
- {
- 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);
-
- 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--)
- {
- 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)
{
@@ -4530,7 +4210,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
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 */
@@ -4544,12 +4224,12 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
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 */
+#endif /* SAFE_MIXED */
if (current_drive->audio_state==audio_playing)
{
i=cc_Pause_Resume(1);
@@ -4584,7 +4264,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
msg(DBG_IOC,"ioctl: CDROMPLAYTRKIND entered.\n");
#ifdef SAFE_MIXED
if (current_drive->has_data>1) RETURN_UP(-EBUSY);
-#endif /* SAFE_MIXED */
+#endif /* SAFE_MIXED */
if (current_drive->audio_state==audio_playing)
{
msg(DBG_IOX,"CDROMPLAYTRKIND: already audio_playing.\n");
@@ -4654,13 +4334,13 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
cc_DriveReset();
#endif
RETURN_UP(i);
-
+
case CDROMSTART: /* Spin up the drive */
msg(DBG_IOC,"ioctl: CDROMSTART entered.\n");
cc_SpinUp();
current_drive->audio_state=0;
RETURN_UP(0);
-
+
case CDROMVOLCTRL: /* Volume control */
msg(DBG_IOC,"ioctl: CDROMVOLCTRL entered.\n");
memcpy(&volctrl,(char *) arg,sizeof(volctrl));
@@ -4670,7 +4350,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
current_drive->vol_ctrl1=volctrl.channel1;
i=cc_SetVolume();
RETURN_UP(0);
-
+
case CDROMVOLREAD: /* read Volume settings from drive */
msg(DBG_IOC,"ioctl: CDROMVOLREAD entered.\n");
st=cc_GetVolume();
@@ -4694,7 +4374,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
if (i<0) {
j=cc_ReadError(); /* clear out error status from drive */
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!
It makes it work properly! --AJK */
if (current_drive->CD_changed==0xFF) {
@@ -4715,8 +4395,8 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
}
}
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!
Lets do this right with proper hardware register reading!
*/
@@ -4775,7 +4455,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
SC.cdsc_trk,SC.cdsc_ind,
SC.cdsc_absaddr,SC.cdsc_reladdr);
RETURN_UP(0);
-
+
default:
msg(DBG_IOC,"ioctl: unknown function request %04X\n", cmd);
RETURN_UP(-EINVAL);
@@ -4788,7 +4468,7 @@ static int sbpcd_audio_ioctl(struct cdrom_device_info *cdi, u_int cmd,
static void sbp_transfer(struct request *req)
{
long offs;
-
+
while ( (req->nr_sectors > 0) &&
(req->sector/4 >= current_drive->sbp_first_frame) &&
(req->sector/4 <= current_drive->sbp_last_frame) )
@@ -4807,11 +4487,11 @@ static void sbp_transfer(struct request *req)
*
* 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,
- * 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
* 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?
* If so, we should copy end_request here, and do it right.. (or
@@ -4883,19 +4563,19 @@ static void do_sbpcd_request(request_queue_t * q)
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)
@@ -4914,10 +4594,10 @@ static void do_sbpcd_request(request_queue_t * q)
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 */
-
+#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--)
@@ -4940,7 +4620,7 @@ static void do_sbpcd_request(request_queue_t * q)
{
#ifdef SAFE_MIXED
current_drive->has_data=2; /* is really a data disk */
-#endif /* SAFE_MIXED */
+#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);
@@ -4951,7 +4631,7 @@ static void do_sbpcd_request(request_queue_t * q)
goto request_loop;
}
}
-
+
err_done:
#if OLD_BUSY
busy_data=0;
@@ -4976,7 +4656,7 @@ static void sbp_read_cmd(struct request *req)
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;
@@ -4993,7 +4673,7 @@ static void sbp_read_cmd(struct request *req)
current_drive->sbp_read_frames=1;
}
}
-
+
flags_cmd_out = f_putcmd | f_respo2 | f_ResponseStatus | f_obey_p_check;
clr_cmdbuf();
if (famV_drive)
@@ -5092,7 +4772,7 @@ static int sbp_data(struct request *req)
int success;
int wait;
int duration;
-
+
error_flag=0;
success=0;
#if LONG_TIMING
@@ -5105,12 +4785,12 @@ static int sbp_data(struct request *req)
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)
+ while (!timed_out_data)
{
if (current_drive->f_multisession) try=maxtim_data*4;
else try=maxtim_data;
@@ -5207,9 +4887,9 @@ static int sbp_data(struct request *req)
else
{
sbp_sleep(1);
- OUT(CDo_sel_i_d,0);
+ OUT(CDo_sel_i_d,0);
i=inb(CDi_status);
- }
+ }
if (!(i&s_not_data_ready))
{
OUT(CDo_sel_i_d,1);
@@ -5311,7 +4991,7 @@ static int sbp_data(struct request *req)
}
SBPCD_STI;
}
-
+
#if 0
if (!success)
#endif
@@ -5370,7 +5050,326 @@ 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);
+ 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);
+
+ 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);
+ }
+
+ if (current_drive->sbp_audsiz>0)
+ {
+ current_drive->aud_buf=(u_char *) vmalloc(current_drive->sbp_audsiz*CD_FRAMESIZE_RAW);
+ if (current_drive->aud_buf==NULL)
+ {
+ 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);
+
+ 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--)
+ {
+ 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_block_media_changed(struct gendisk *disk)
@@ -5478,10 +5477,9 @@ static struct cdrom_device_ops sbpcd_dops = {
.get_mcn = sbpcd_get_mcn,
.reset = sbpcd_reset,
.audio_ioctl = sbpcd_audio_ioctl,
- .dev_ioctl = sbpcd_dev_ioctl,
.capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
- CDC_MCN | CDC_PLAY_AUDIO | CDC_IOCTLS,
+ CDC_MCN | CDC_PLAY_AUDIO,
.n_minors = 1,
};