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

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

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