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

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