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

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