root/drivers/scsi/sg.c

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

DEFINITIONS

This source file includes following definitions.
  1. sg_ioctl
  2. sg_open
  3. sg_close
  4. sg_malloc
  5. sg_free
  6. sg_read
  7. sg_command_done
  8. sg_write
  9. sg_detect
  10. sg_init
  11. sg_attach
  12. sg_detach

   1 /*
   2    History:
   3     Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user 
   4      process control of SCSI devices.
   5     Development Sponsored by Killy Corp. NY NY
   6     
   7     Borrows code from st driver.
   8 */
   9 
  10 #include <linux/fs.h>
  11 #include <linux/kernel.h>
  12 #include <linux/sched.h>
  13 #include <linux/string.h>
  14 #include <linux/mm.h>
  15 #include <linux/errno.h>
  16 #include <linux/mtio.h>
  17 #include <linux/ioctl.h>
  18 #include <linux/fcntl.h>
  19 #include <asm/io.h>
  20 #include <asm/segment.h>
  21 #include <asm/system.h>
  22 
  23 #include "../block/blk.h"
  24 #include "scsi.h"
  25 #include "hosts.h"
  26 #include "scsi_ioctl.h"
  27 #include "sg.h"
  28 
  29 static void sg_init(void);
  30 static int sg_attach(Scsi_Device *);
  31 static int sg_detect(Scsi_Device *);
  32 static void sg_detach(Scsi_Device *);
  33 
  34 
  35 struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", 0xff, 
  36                                              SCSI_GENERIC_MAJOR, 0, 0, 0, 0,
  37                                              sg_detect, sg_init,
  38                                              NULL, sg_attach, sg_detach};
  39 
  40 #ifdef SG_BIG_BUFF
  41 static char *big_buff;
  42 static struct wait_queue *big_wait;   /* wait for buffer available */
  43 static int big_inuse=0;
  44 #endif
  45 
  46 struct scsi_generic
  47  {
  48   Scsi_Device *device;
  49   int users;   /* how many people have it open? */
  50   struct wait_queue *generic_wait; /* wait for device to be available */
  51   struct wait_queue *read_wait;    /* wait for response */
  52   struct wait_queue *write_wait;   /* wait for free buffer */
  53   int timeout; /* current default value for device */
  54   int buff_len; /* length of current buffer */
  55   char *buff;   /* the buffer */
  56   struct sg_header header; /* header of pending command */
  57   char exclude; /* opened for exclusive access */
  58   char pending;  /* don't accept writes now */
  59   char complete; /* command complete allow a read */
  60  };
  61 
  62 static struct scsi_generic *scsi_generics=NULL;
  63 static void sg_free(char *buff,int size);
  64 
  65 static int sg_ioctl(struct inode * inode,struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
  66              unsigned int cmd_in, unsigned long arg)
  67  {
  68   int dev = MINOR(inode->i_rdev);
  69   if ((dev<0) || (dev>=sg_template.dev_max))
  70    return -ENXIO;
  71   switch(cmd_in)
  72    {
  73     case SG_SET_TIMEOUT:
  74      scsi_generics[dev].timeout=get_fs_long((int *) arg);
  75      return 0;
  76     case SG_GET_TIMEOUT:
  77      return scsi_generics[dev].timeout;
  78     default:
  79      return scsi_ioctl(scsi_generics[dev].device, cmd_in, (void *) arg);
  80    }
  81  }
  82 
  83 static int sg_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
  84  {
  85   int dev=MINOR(inode->i_rdev);
  86   int flags=filp->f_flags;
  87   if (dev>=sg_template.dev_max || !scsi_generics[dev].device)
  88    return -ENXIO;
  89   if (O_RDWR!=(flags & O_ACCMODE))
  90    return -EACCES;
  91   if (flags & O_EXCL)
  92    {
  93     while(scsi_generics[dev].users)
  94      {
  95       if (flags & O_NONBLOCK)
  96        return -EBUSY;
  97       interruptible_sleep_on(&scsi_generics[dev].generic_wait);
  98       if (current->signal & ~current->blocked)
  99        return -ERESTARTSYS;
 100      }
 101     scsi_generics[dev].exclude=1;
 102    }
 103   else
 104    while(scsi_generics[dev].exclude)
 105     {
 106      if (flags & O_NONBLOCK)
 107       return -EBUSY;
 108      interruptible_sleep_on(&scsi_generics[dev].generic_wait);
 109      if (current->signal & ~current->blocked)
 110       return -ERESTARTSYS;
 111     }
 112   if (!scsi_generics[dev].users && scsi_generics[dev].pending && scsi_generics[dev].complete)
 113    {
 114     if (scsi_generics[dev].buff != NULL)
 115       sg_free(scsi_generics[dev].buff,scsi_generics[dev].buff_len);
 116     scsi_generics[dev].buff=NULL;
 117     scsi_generics[dev].pending=0;
 118    }
 119   if (!scsi_generics[dev].users)
 120    scsi_generics[dev].timeout=SG_DEFAULT_TIMEOUT;
 121   if (scsi_generics[dev].device->host->hostt->usage_count)
 122     (*scsi_generics[dev].device->host->hostt->usage_count)++;
 123   scsi_generics[dev].users++;
 124   return 0;
 125  }
 126 
 127 static void sg_close(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 128  {
 129   int dev=MINOR(inode->i_rdev);
 130   scsi_generics[dev].users--;
 131   if (scsi_generics[dev].device->host->hostt->usage_count)
 132     (*scsi_generics[dev].device->host->hostt->usage_count)--;
 133   scsi_generics[dev].exclude=0;
 134   wake_up(&scsi_generics[dev].generic_wait);
 135  }
 136 
 137 static char *sg_malloc(int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 138  {
 139   if (size<=4096)
 140    return (char *) scsi_malloc(size);
 141 #ifdef SG_BIG_BUFF
 142   if (size<SG_BIG_BUFF)
 143    {
 144     while(big_inuse)
 145      {
 146       interruptible_sleep_on(&big_wait);
 147       if (current->signal & ~current->blocked)
 148        return NULL;
 149      }
 150     big_inuse=1;
 151     return big_buff;
 152    }
 153 #endif   
 154   return NULL;
 155  }
 156 
 157 static void sg_free(char *buff,int size) 
     /* [previous][next][first][last][top][bottom][index][help] */
 158  {
 159 #ifdef SG_BIG_BUFF
 160   if (buff==big_buff)
 161    {
 162     big_inuse=0;
 163     wake_up(&big_wait);
 164     return;
 165    }
 166 #endif
 167   scsi_free(buff,size);
 168  }
 169 
 170 static int sg_read(struct inode *inode,struct file *filp,char *buf,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 171  {
 172   int dev=MINOR(inode->i_rdev);
 173   int i;
 174   struct scsi_generic *device=&scsi_generics[dev];
 175   if ((i=verify_area(VERIFY_WRITE,buf,count)))
 176    return i;
 177   while(!device->pending || !device->complete)
 178    {
 179     if (filp->f_flags & O_NONBLOCK)
 180      return -EWOULDBLOCK;
 181     interruptible_sleep_on(&device->read_wait);
 182     if (current->signal & ~current->blocked)
 183      return -ERESTARTSYS;
 184    }
 185   device->header.pack_len=device->header.reply_len;
 186   device->header.result=0;
 187   if (count>=sizeof(struct sg_header))
 188    {
 189     memcpy_tofs(buf,&device->header,sizeof(struct sg_header));
 190     buf+=sizeof(struct sg_header);
 191     if (count>device->header.pack_len)
 192      count=device->header.pack_len;
 193     if (count > sizeof(struct sg_header)) {
 194        memcpy_tofs(buf,device->buff,count-sizeof(struct sg_header));
 195     }
 196    }
 197   else
 198    count=0;
 199   sg_free(device->buff,device->buff_len);
 200   device->buff = NULL;
 201   device->pending=0;
 202   wake_up(&device->write_wait);
 203   return count;
 204  }
 205 
 206 static void sg_command_done(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 207  {
 208   int dev=SCpnt->request.dev;
 209   struct scsi_generic *device=&scsi_generics[dev];
 210   if (!device->pending)
 211    {
 212     printk("unexpected done for sg %d\n",dev);
 213     SCpnt->request.dev=-1;
 214     return;
 215    }
 216   memcpy(device->header.sense_buffer, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer));
 217   if (SCpnt->sense_buffer[0])
 218    {
 219     device->header.result=EIO;
 220    }
 221   else
 222    device->header.result=SCpnt->result;
 223   device->complete=1;
 224   SCpnt->request.dev=-1;
 225   wake_up(&scsi_generics[dev].read_wait);
 226  }
 227 
 228 static int sg_write(struct inode *inode,struct file *filp,char *buf,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 229  {
 230   int dev=MINOR(inode->i_rdev);
 231   Scsi_Cmnd *SCpnt;
 232   int bsize,size,amt,i;
 233   unsigned char opcode;
 234   unsigned char cmnd[MAX_COMMAND_SIZE];
 235   struct scsi_generic *device=&scsi_generics[dev];
 236 
 237   if ((i=verify_area(VERIFY_READ,buf,count)))
 238    return i;
 239   /*
 240    * The minimum scsi command length is 6 bytes.  If we get anything less than this,
 241    * it is clearly bogus.
 242    */
 243   if (count<(sizeof(struct sg_header) + 6))
 244    return -EIO;
 245   /* make sure we can fit */
 246   while(device->pending)
 247    {
 248     if (filp->f_flags & O_NONBLOCK)
 249      return -EWOULDBLOCK;
 250 #ifdef DEBUG
 251     printk("sg_write: sleeping on pending request\n");
 252 #endif     
 253     interruptible_sleep_on(&device->write_wait);
 254     if (current->signal & ~current->blocked)
 255      return -ERESTARTSYS;
 256    }
 257   device->pending=1;
 258   device->complete=0;
 259   memcpy_fromfs(&device->header,buf,sizeof(struct sg_header));
 260   /* fix input size */
 261   device->header.pack_len=count;
 262   buf+=sizeof(struct sg_header);
 263   bsize=(device->header.pack_len>device->header.reply_len) ? device->header.pack_len : device->header.reply_len;
 264   bsize-=sizeof(struct sg_header);
 265   amt=bsize;
 266   if (!bsize)
 267    bsize++;
 268   bsize=(bsize+511) & ~511;
 269   if ((bsize<0) || !(device->buff=sg_malloc(device->buff_len=bsize)))
 270    {
 271     device->pending=0;
 272     wake_up(&device->write_wait);
 273     return -ENOMEM;
 274    }
 275 #ifdef DEBUG
 276   printk("allocating device\n");
 277 #endif
 278   if (!(SCpnt=allocate_device(NULL,device->device, !(filp->f_flags & O_NONBLOCK))))
 279    {
 280     device->pending=0;
 281     wake_up(&device->write_wait);
 282     sg_free(device->buff,device->buff_len);
 283     device->buff = NULL;
 284     return -EWOULDBLOCK;
 285    } 
 286 #ifdef DEBUG
 287   printk("device allocated\n");
 288 #endif    
 289   /* now issue command */
 290   SCpnt->request.dev=dev;
 291   SCpnt->sense_buffer[0]=0;
 292   opcode = get_fs_byte(buf);
 293   size=COMMAND_SIZE(opcode);
 294   if (opcode >= 0xc0 && device->header.twelve_byte) size = 12;
 295   SCpnt->cmd_len = size;
 296   /*
 297    * Verify that the user has actually passed enough bytes for this command.
 298    */
 299   if (count<(sizeof(struct sg_header) + size))
 300     {
 301       device->pending=0;
 302       wake_up(&device->write_wait);
 303       sg_free(device->buff,device->buff_len);
 304       device->buff = NULL;
 305       return -EIO;
 306     }
 307 
 308   memcpy_fromfs(cmnd,buf,size);
 309   buf+=size;
 310   memcpy_fromfs(device->buff,buf,device->header.pack_len-size-sizeof(struct sg_header));
 311   cmnd[1]=(cmnd[1] & 0x1f) | (device->device->lun<<5);
 312 #ifdef DEBUG
 313   printk("do cmd\n");
 314 #endif
 315   scsi_do_cmd (SCpnt,(void *) cmnd,
 316                (void *) device->buff,amt,
 317                sg_command_done,device->timeout,SG_DEFAULT_RETRIES);
 318 #ifdef DEBUG
 319   printk("done cmd\n");
 320 #endif               
 321   return count;
 322  }
 323 
 324 static struct file_operations sg_fops = {
 325    NULL,            /* lseek */
 326    sg_read,         /* read */
 327    sg_write,        /* write */
 328    NULL,            /* readdir */
 329    NULL,            /* select */
 330    sg_ioctl,        /* ioctl */
 331    NULL,            /* mmap */
 332    sg_open,         /* open */
 333    sg_close,        /* release */
 334    NULL             /* fsync */
 335 };
 336 
 337 
 338 static int sg_detect(Scsi_Device * SDp){
     /* [previous][next][first][last][top][bottom][index][help] */
 339   ++sg_template.dev_noticed;
 340   return 1;
 341 }
 342 
 343 /* Driver initialization */
 344 static void sg_init()
     /* [previous][next][first][last][top][bottom][index][help] */
 345  {
 346    static int sg_registered = 0;
 347    
 348    if (sg_template.dev_noticed == 0) return;
 349 
 350    if(!sg_registered) {
 351      if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops)) 
 352        {
 353          printk("Unable to get major %d for generic SCSI device\n",
 354                 SCSI_GENERIC_MAJOR);
 355          return;
 356        }
 357      sg_registered++;
 358    }
 359 
 360    /* If we have already been through here, return */
 361    if(scsi_generics) return;
 362 
 363 #ifdef DEBUG
 364   printk("sg: Init generic device.\n");
 365 #endif
 366 
 367 #ifdef SG_BIG_BUFF
 368   big_buff= (char *) scsi_init_malloc(SG_BIG_BUFF, GFP_ATOMIC | GFP_DMA);
 369 #endif
 370 
 371    scsi_generics = (struct scsi_generic *) 
 372      scsi_init_malloc((sg_template.dev_noticed + SG_EXTRA_DEVS) 
 373                       * sizeof(struct scsi_generic), GFP_ATOMIC);
 374    memset(scsi_generics, 0, (sg_template.dev_noticed + SG_EXTRA_DEVS)
 375           * sizeof(struct scsi_generic));
 376 
 377    sg_template.dev_max = sg_template.dev_noticed + SG_EXTRA_DEVS;
 378  }
 379 
 380 static int sg_attach(Scsi_Device * SDp)
     /* [previous][next][first][last][top][bottom][index][help] */
 381  {
 382    struct scsi_generic * gpnt;
 383    int i;
 384 
 385    if(sg_template.nr_dev >= sg_template.dev_max) 
 386      {
 387        SDp->attached--;
 388        return 1;
 389      }
 390 
 391    for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++) 
 392      if(!gpnt->device) break;
 393 
 394    if(i >= sg_template.dev_max) panic ("scsi_devices corrupt (sg)");
 395 
 396    scsi_generics[i].device=SDp;
 397    scsi_generics[i].users=0;
 398    scsi_generics[i].generic_wait=NULL;
 399    scsi_generics[i].read_wait=NULL;
 400    scsi_generics[i].write_wait=NULL;
 401    scsi_generics[i].buff=NULL;
 402    scsi_generics[i].exclude=0;
 403    scsi_generics[i].pending=0;
 404    scsi_generics[i].timeout=SG_DEFAULT_TIMEOUT;
 405    sg_template.nr_dev++;
 406    return 0;
 407  };
 408 
 409 
 410 
 411 static void sg_detach(Scsi_Device * SDp)
     /* [previous][next][first][last][top][bottom][index][help] */
 412 {
 413   struct scsi_generic * gpnt;
 414   int i;
 415   
 416   for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++) 
 417     if(gpnt->device == SDp) {
 418       gpnt->device = NULL;
 419       SDp->attached--;
 420       sg_template.nr_dev--;
 421       return;
 422     }
 423   return;
 424 }
 425 
 426 /*
 427  * Overrides for Emacs so that we follow Linus's tabbing style.
 428  * Emacs will notice this stuff at the end of the file and automatically
 429  * adjust the settings for this buffer only.  This must remain at the end
 430  * of the file.
 431  * ---------------------------------------------------------------------------
 432  * Local variables:
 433  * c-indent-level: 8
 434  * c-brace-imaginary-offset: 0
 435  * c-brace-offset: -8
 436  * c-argdecl-indent: 8
 437  * c-label-offset: -8
 438  * c-continued-statement-offset: 8
 439  * c-continued-brace-offset: 0
 440  * End:
 441  */

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