root/kernel/blk_drv/scsi/sr_ioctl.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lock_sr_ioctl
  2. unlock_sr_ioctl
  3. sr_ioctl_done
  4. do_ioctl
  5. check_cdrom_media_change
  6. sr_ioctl

   1 #include <linux/config.h>
   2 #ifdef CONFIG_BLK_DEV_SR
   3 #include <linux/kernel.h>
   4 #include <linux/sched.h>
   5 #include <linux/fs.h>
   6 #include <asm/segment.h>
   7 #include <linux/errno.h>
   8 
   9 #include "../blk.h"
  10 #include "scsi.h"
  11 #include "sr.h"
  12 
  13 #include <linux/cdrom.h>
  14 
  15 #define IOCTL_RETRIES 3
  16 /* The CDROM is fairly slow, so we need a little extra time */
  17 #define IOCTL_TIMEOUT 200
  18 
  19 static u_char   sr_cmd[10];
  20 static u_char   data_buffer[255];
  21 static u_char   sense_buffer[255];
  22 static int      the_result;
  23 
  24 static struct wait_queue *sr_cmd_wait = NULL;   /* For waiting until cmd done*/
  25 static u_char   sr_lock = 0;   /* To make sure that only one person is doing
  26                                   an ioctl at one time */
  27 static int      target;
  28 
  29 extern int scsi_ioctl (int dev, int cmd, void *arg);
  30 
  31 static void lock_sr_ioctl( void )
     /* [previous][next][first][last][top][bottom][index][help] */
  32 {
  33   /* We do not use wakeup here because there could conceivably be three
  34      processes trying to get at the drive simultaneously, and we would
  35      be screwed if that happened.
  36      */
  37 
  38         while (sr_lock);
  39         sr_lock = 1;
  40 }
  41 
  42 static void unlock_sr_ioctl( void )
     /* [previous][next][first][last][top][bottom][index][help] */
  43 {
  44         sr_lock = 0;
  45 }
  46 
  47 static void sr_ioctl_done( int host, int result )
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49         the_result = result;
  50         wake_up(&sr_cmd_wait);
  51 }
  52 
  53 /* We do our own retries because we want to know what the specific
  54    error code is.  Normally the UNIT_ATTENTION code will automatically
  55    clear after one error */
  56 
  57 static int do_ioctl( void )
     /* [previous][next][first][last][top][bottom][index][help] */
  58 {
  59         int retries = IOCTL_RETRIES;
  60 retry:     
  61 
  62         the_result = -1;
  63 
  64         scsi_do_cmd(scsi_CDs[target].device->host_no, scsi_CDs[target].device->id,
  65                     (void *) sr_cmd, (void *) data_buffer, 255, sr_ioctl_done, 
  66                     IOCTL_TIMEOUT, (void *) sense_buffer, 0);
  67 
  68         while (the_result < 0) sleep_on(&sr_cmd_wait);
  69 
  70         if(driver_byte(the_result) != 0 && 
  71            (sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
  72           scsi_CDs[target].changed = 1;
  73           printk("Disc change detected.\n");
  74         };
  75 
  76         if (the_result && retries)
  77                 {
  78                 retries--;
  79                 goto retry;
  80                 }
  81 
  82 /* Minimal error checking.  Ignore cases we know about, and report the rest. */
  83         if(driver_byte(the_result) != 0)
  84           switch(sense_buffer[2] & 0xf) {
  85           case UNIT_ATTENTION:
  86             scsi_CDs[target].changed = 1;
  87             printk("Disc change detected.\n");
  88             break;
  89           case NOT_READY: /* This happens if there is no disc in drive */
  90             printk("CDROM not ready.  Make sure there is a disc in the drive.\n");
  91             break;
  92           case ILLEGAL_REQUEST:
  93             printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n");
  94             break;
  95           default:
  96             printk("SCSI CD error: host %d id %d lun %d return code = %03x\n", 
  97                    scsi_CDs[target].device->host_no, 
  98                    scsi_CDs[target].device->id,
  99                    scsi_CDs[target].device->lun,
 100                    the_result);
 101             printk("\tSense class %x, sense error %x, extended sense %x\n",
 102                    sense_class(sense_buffer[0]), 
 103                    sense_error(sense_buffer[0]),
 104                    sense_buffer[2] & 0xf);
 105             
 106         };
 107         return the_result;
 108 }
 109         
 110 /*
 111  * This function checks to see if the media has been changed in the
 112  * CDROM drive.  It is possible that we have already sensed a change,
 113  * or the drive may have sensed one and not yet reported it.  We must
 114  * be ready for either case. This function always reports the current
 115  * value of the changed bit.  If flag is 0, then the changed bit is reset.
 116  * This function could be done as an ioctl, but we would need to have
 117  * an inode for that to work, and we do not always have one.
 118  */
 119 
 120 int check_cdrom_media_change(int full_dev, int flag){
     /* [previous][next][first][last][top][bottom][index][help] */
 121         int retval;
 122 
 123         lock_sr_ioctl();
 124 
 125         target =  MINOR(full_dev);
 126 
 127         if (target >= NR_SR) {
 128                 printk("CD-ROM request error: invalid device.\n");
 129                 unlock_sr_ioctl();
 130                 return 0;
 131         };
 132 
 133         sr_cmd[0] = TEST_UNIT_READY;
 134         sr_cmd[1] = (scsi_CDs[target].device->lun << 5) & 0xe0;
 135         sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
 136 
 137         retval = do_ioctl();
 138 
 139         if(retval){ /* Unable to test, unit probably not ready.  This usually
 140                      means there is no disc in the drive.  Mark as changed,
 141                      and we will figure it out later once the drive is
 142                      available again.  */
 143 
 144           scsi_CDs[target].changed = 1;
 145           unlock_sr_ioctl();
 146           return 1; /* This will force a flush, if called from
 147                        check_disk_change */
 148         };
 149 
 150         retval = scsi_CDs[target].changed;
 151         if(!flag) scsi_CDs[target].changed = 0;
 152         unlock_sr_ioctl();
 153 
 154         return retval;
 155 }
 156 
 157 int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159         int dev = inode->i_rdev;
 160         int result;
 161 
 162         target = MINOR(dev);
 163 
 164         switch (cmd) 
 165                 {
 166                 /* linux-specific */
 167                 case CDROMDOORUNLOCK:
 168                         lock_sr_ioctl();
 169 
 170                         sr_cmd[0] = ALLOW_MEDIUM_REMOVAL;
 171                         sr_cmd[1] = scsi_CDs[target].device->lun << 5;
 172                         sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
 173                         sr_cmd[4] = SR_REMOVAL_ALLOW;
 174 
 175                         result = do_ioctl();
 176 
 177                         unlock_sr_ioctl();
 178                         return result;
 179 
 180                 case CDROMDOORLOCK:
 181                         lock_sr_ioctl();
 182 
 183                         sr_cmd[0] = ALLOW_MEDIUM_REMOVAL;
 184                         sr_cmd[1] = scsi_CDs[target].device->lun << 5;
 185                         sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
 186                         sr_cmd[4] = SR_REMOVAL_PREVENT;
 187 
 188                         result = do_ioctl();
 189 
 190                         unlock_sr_ioctl();
 191                         return result;
 192 
 193                 /* Sun-compatible */
 194                 case CDROMPAUSE:
 195                         lock_sr_ioctl();
 196 
 197                         sr_cmd[0] = SCMD_PAUSE_RESUME;
 198                         sr_cmd[1] = scsi_CDs[target].device->lun << 5;
 199                         sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
 200                         sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
 201                         sr_cmd[8] = 1;
 202                         sr_cmd[9] = 0;
 203 
 204                         result = do_ioctl();
 205 
 206                         unlock_sr_ioctl();
 207                         return result;
 208 
 209                 case CDROMRESUME:
 210                         lock_sr_ioctl();
 211 
 212                         sr_cmd[0] = SCMD_PAUSE_RESUME;
 213                         sr_cmd[1] = scsi_CDs[target].device->lun << 5;
 214                         sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
 215                         sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
 216                         sr_cmd[8] = 0;
 217                         sr_cmd[9] = 0;
 218 
 219                         result = do_ioctl();
 220 
 221                         unlock_sr_ioctl();
 222                         return result;
 223 
 224                 case CDROMPLAYMSF:
 225                         {
 226                         struct cdrom_msf msf;
 227                         lock_sr_ioctl();
 228 
 229                         memcpy_fromfs(&msf, (void *) arg, sizeof(msf));
 230 
 231                         sr_cmd[0] = SCMD_PLAYAUDIO_MSF;
 232                         sr_cmd[1] = scsi_CDs[target].device->lun << 5;
 233                         sr_cmd[2] = 0;
 234                         sr_cmd[3] = msf.cdmsf_min0;
 235                         sr_cmd[4] = msf.cdmsf_sec0;
 236                         sr_cmd[5] = msf.cdmsf_frame0;
 237                         sr_cmd[6] = msf.cdmsf_min1;
 238                         sr_cmd[7] = msf.cdmsf_sec1;
 239                         sr_cmd[8] = msf.cdmsf_frame1;
 240                         sr_cmd[9] = 0;
 241 
 242                         result = do_ioctl();
 243 
 244                         unlock_sr_ioctl();
 245                         return result;
 246                         }
 247 
 248                 case CDROMPLAYTRKIND:
 249                         {
 250                         struct cdrom_ti ti;
 251                         lock_sr_ioctl();
 252 
 253                         memcpy_fromfs(&ti, (void *) arg, sizeof(ti));
 254 
 255                         sr_cmd[0] = SCMD_PLAYAUDIO_TI;
 256                         sr_cmd[1] = scsi_CDs[target].device->lun << 5;
 257                         sr_cmd[2] = 0;
 258                         sr_cmd[3] = 0;
 259                         sr_cmd[4] = ti.cdti_trk0;
 260                         sr_cmd[5] = ti.cdti_ind0;
 261                         sr_cmd[6] = 0;
 262                         sr_cmd[7] = ti.cdti_trk1;
 263                         sr_cmd[8] = ti.cdti_ind1;
 264                         sr_cmd[9] = 0;
 265 
 266                         result = do_ioctl();
 267 
 268                         unlock_sr_ioctl();
 269                         return result;
 270                         }
 271 
 272                 case CDROMREADTOCHDR:
 273                         return -EINVAL;
 274                 case CDROMREADTOCENTRY:
 275                         return -EINVAL;
 276 
 277                 case CDROMSTOP:
 278                         lock_sr_ioctl();
 279 
 280                         sr_cmd[0] = START_STOP;
 281                         sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
 282                         sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
 283                         sr_cmd[4] = 0;
 284 
 285                         result = do_ioctl();
 286 
 287                         unlock_sr_ioctl();
 288                         return result;
 289                         
 290                 case CDROMSTART:
 291                         lock_sr_ioctl();
 292 
 293                         sr_cmd[0] = START_STOP;
 294                         sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
 295                         sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
 296                         sr_cmd[4] = 1;
 297 
 298                         result = do_ioctl();
 299 
 300                         unlock_sr_ioctl();
 301                         return result;
 302 
 303                 case CDROMEJECT:
 304                         lock_sr_ioctl();
 305 
 306                         sr_cmd[0] = START_STOP;
 307                         sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
 308                         sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
 309                         sr_cmd[4] = 0x02;
 310 
 311                         result = do_ioctl();
 312 
 313                         unlock_sr_ioctl();
 314                         return result;
 315 
 316                 case CDROMVOLCTRL:
 317                         return -EINVAL;
 318                 case CDROMSUBCHNL:
 319                         return -EINVAL;
 320                 case CDROMREADMODE2:
 321                         return -EINVAL;
 322                 case CDROMREADMODE1:
 323                         return -EINVAL;
 324 
 325                 RO_IOCTLS(dev,arg);
 326                 default:
 327                         return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
 328                 }
 329 }
 330 
 331 #endif

/* [previous][next][first][last][top][bottom][index][help] */