[PATCH] kill cdrom ->dev_ioctl method
[linux-2.6.git] / drivers / cdrom / sbpcd.c
index 466e9c2..4760f51 100644 (file)
@@ -4160,332 +4160,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 +4204,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 +4218,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 +4258,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 +4328,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 +4344,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 +4368,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 +4389,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 +4449,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 +4462,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 +4481,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 +4557,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 +4588,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 +4614,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 +4625,7 @@ static void do_sbpcd_request(request_queue_t * q)
                        goto request_loop;
                }
        }
-       
+
  err_done:
 #if OLD_BUSY
        busy_data=0;
@@ -4976,7 +4650,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 +4667,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 +4766,7 @@ static int sbp_data(struct request *req)
        int success;
        int wait;
        int duration;
-       
+
        error_flag=0;
        success=0;
 #if LONG_TIMING
@@ -5105,12 +4779,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 +4881,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 +4985,7 @@ static int sbp_data(struct request *req)
                }
                SBPCD_STI;
        }
-       
+
 #if 0
        if (!success)
 #endif
@@ -5370,7 +5044,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 +5471,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,
 };