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_select
  10. sg_detect
  11. sg_init
  12. sg_attach
  13. sg_detach
  14. init_module
  15. cleanup_module

   1 /*
   2  *  History:
   3  *  Started: Aug 9 by Lawrence Foard (entropy@world.std.com), 
   4  *           to allow user process control of SCSI devices.
   5  *  Development Sponsored by Killy Corp. NY NY
   6  *   
   7  *  Borrows code from st driver.
   8  */
   9 #ifdef MODULE
  10 #include <linux/autoconf.h>
  11 #include <linux/module.h>
  12 #include <linux/version.h>
  13 #endif /* MODULE */
  14 
  15 #include <linux/fs.h>
  16 #include <linux/kernel.h>
  17 #include <linux/sched.h>
  18 #include <linux/string.h>
  19 #include <linux/mm.h>
  20 #include <linux/errno.h>
  21 #include <linux/mtio.h>
  22 #include <linux/ioctl.h>
  23 #include <linux/fcntl.h>
  24 #include <asm/io.h>
  25 #include <asm/segment.h>
  26 #include <asm/system.h>
  27 
  28 #include "../block/blk.h"
  29 #include "scsi.h"
  30 #include "hosts.h"
  31 #include "scsi_ioctl.h"
  32 #include "sg.h"
  33 
  34 static int sg_init(void);
  35 static int sg_attach(Scsi_Device *);
  36 static int sg_detect(Scsi_Device *);
  37 static void sg_detach(Scsi_Device *);
  38 
  39 
  40 struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", NULL, 0xff, 
  41                                                SCSI_GENERIC_MAJOR, 0, 0, 0, 0,
  42                                                sg_detect, sg_init,
  43                                                NULL, sg_attach, sg_detach};
  44 
  45 #ifdef SG_BIG_BUFF
  46 static char *big_buff = NULL;
  47 static struct wait_queue *big_wait;   /* wait for buffer available */
  48 static int big_inuse=0;
  49 #endif
  50 
  51 struct scsi_generic
  52 {
  53     Scsi_Device *device;
  54     int users;   /* how many people have it open? */
  55     struct wait_queue *generic_wait; /* wait for device to be available */
  56     struct wait_queue *read_wait;    /* wait for response */
  57     struct wait_queue *write_wait;   /* wait for free buffer */
  58     int timeout; /* current default value for device */
  59     int buff_len; /* length of current buffer */
  60     char *buff;   /* the buffer */
  61     struct sg_header header; /* header of pending command */
  62     char exclude; /* opened for exclusive access */
  63     char pending;  /* don't accept writes now */
  64     char complete; /* command complete allow a read */
  65 };
  66 
  67 static struct scsi_generic *scsi_generics=NULL;
  68 static void sg_free(char *buff,int size);
  69 
  70 static int sg_ioctl(struct inode * inode,struct file * file,
     /* [previous][next][first][last][top][bottom][index][help] */
  71                     unsigned int cmd_in, unsigned long arg)
  72 {
  73     int result;
  74     int dev = MINOR(inode->i_rdev);
  75     if ((dev<0) || (dev>=sg_template.dev_max))
  76         return -ENXIO;
  77     switch(cmd_in)
  78     {
  79     case SG_SET_TIMEOUT:
  80         result = verify_area(VERIFY_READ, (const void *)arg, sizeof(long));
  81         if (result) return result;
  82 
  83         scsi_generics[dev].timeout=get_user((int *) arg);
  84         return 0;
  85     case SG_GET_TIMEOUT:
  86         return scsi_generics[dev].timeout;
  87     default:
  88         return scsi_ioctl(scsi_generics[dev].device, cmd_in, (void *) arg);
  89     }
  90 }
  91 
  92 static int sg_open(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
  93 {
  94     int dev=MINOR(inode->i_rdev);
  95     int flags=filp->f_flags;
  96     if (dev>=sg_template.dev_max || !scsi_generics[dev].device)
  97         return -ENXIO;
  98     if (O_RDWR!=(flags & O_ACCMODE))
  99         return -EACCES;
 100 
 101   /*
 102    * If we want exclusive access, then wait until the device is not
 103    * busy, and then set the flag to prevent anyone else from using it.
 104    */
 105     if (flags & O_EXCL)
 106     {
 107         while(scsi_generics[dev].users)
 108         {
 109             if (flags & O_NONBLOCK)
 110                 return -EBUSY;
 111             interruptible_sleep_on(&scsi_generics[dev].generic_wait);
 112             if (current->signal & ~current->blocked)
 113                 return -ERESTARTSYS;
 114         }
 115         scsi_generics[dev].exclude=1;
 116     }
 117     else
 118         /*
 119          * Wait until nobody has an exclusive open on
 120          * this device.
 121          */
 122         while(scsi_generics[dev].exclude)
 123         {
 124             if (flags & O_NONBLOCK)
 125                 return -EBUSY;
 126             interruptible_sleep_on(&scsi_generics[dev].generic_wait);
 127             if (current->signal & ~current->blocked)
 128                 return -ERESTARTSYS;
 129         }
 130 
 131     /*
 132      * OK, we should have grabbed the device.  Mark the thing so
 133      * that other processes know that we have it, and initialize the
 134      * state variables to known values.
 135      */
 136     if (!scsi_generics[dev].users 
 137         && scsi_generics[dev].pending
 138         && scsi_generics[dev].complete)
 139     {
 140         if (scsi_generics[dev].buff != NULL)
 141             sg_free(scsi_generics[dev].buff,scsi_generics[dev].buff_len);
 142         scsi_generics[dev].buff=NULL;
 143         scsi_generics[dev].pending=0;
 144     }
 145     if (!scsi_generics[dev].users)
 146         scsi_generics[dev].timeout=SG_DEFAULT_TIMEOUT;
 147     if (scsi_generics[dev].device->host->hostt->usage_count)
 148         (*scsi_generics[dev].device->host->hostt->usage_count)++;
 149     if(sg_template.usage_count) (*sg_template.usage_count)++;
 150     scsi_generics[dev].users++;
 151     return 0;
 152 }
 153 
 154 static void sg_close(struct inode * inode, struct file * filp)
     /* [previous][next][first][last][top][bottom][index][help] */
 155 {
 156     int dev=MINOR(inode->i_rdev);
 157     scsi_generics[dev].users--;
 158     if (scsi_generics[dev].device->host->hostt->usage_count)
 159         (*scsi_generics[dev].device->host->hostt->usage_count)--;
 160     if(sg_template.usage_count) (*sg_template.usage_count)--;
 161     scsi_generics[dev].exclude=0;
 162     wake_up(&scsi_generics[dev].generic_wait);
 163 }
 164 
 165 static char *sg_malloc(int size)
     /* [previous][next][first][last][top][bottom][index][help] */
 166 {
 167     if (size<=4096)
 168         return (char *) scsi_malloc(size);
 169 #ifdef SG_BIG_BUFF
 170     if (size<=SG_BIG_BUFF)
 171     {
 172         while(big_inuse)
 173         {
 174             interruptible_sleep_on(&big_wait);
 175             if (current->signal & ~current->blocked)
 176                 return NULL;
 177         }
 178         big_inuse=1;
 179         return big_buff;
 180     }
 181 #endif   
 182     return NULL;
 183 }
 184 
 185 static void sg_free(char *buff,int size) 
     /* [previous][next][first][last][top][bottom][index][help] */
 186 {
 187 #ifdef SG_BIG_BUFF
 188     if (buff==big_buff)
 189     {
 190         big_inuse=0;
 191         wake_up(&big_wait);
 192         return;
 193     }
 194 #endif
 195     scsi_free(buff,size);
 196 }
 197 
 198 /*
 199  * Read back the results of a previous command.  We use the pending and
 200  * complete semaphores to tell us whether the buffer is available for us
 201  * and whether the command is actually done.
 202  */
 203 static int sg_read(struct inode *inode,struct file *filp,char *buf,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 204 {
 205     int dev=MINOR(inode->i_rdev);
 206     int i;
 207     unsigned long flags;
 208     struct scsi_generic *device=&scsi_generics[dev];
 209     if ((i=verify_area(VERIFY_WRITE,buf,count)))
 210         return i;
 211 
 212     /*
 213      * Wait until the command is actually done.
 214      */
 215     save_flags(flags);
 216     cli();
 217     while(!device->pending || !device->complete)
 218     {
 219         if (filp->f_flags & O_NONBLOCK)
 220         {
 221             restore_flags(flags);
 222             return -EWOULDBLOCK;
 223         }
 224         interruptible_sleep_on(&device->read_wait);
 225         if (current->signal & ~current->blocked)
 226         {
 227             restore_flags(flags);
 228             return -ERESTARTSYS;
 229         }
 230     }
 231     restore_flags(flags);
 232 
 233     /*
 234      * Now copy the result back to the user buffer.
 235      */
 236     device->header.pack_len=device->header.reply_len;
 237     device->header.result=0;
 238     if (count>=sizeof(struct sg_header))
 239     {
 240         memcpy_tofs(buf,&device->header,sizeof(struct sg_header));
 241         buf+=sizeof(struct sg_header);
 242         if (count>device->header.pack_len)
 243             count=device->header.pack_len;
 244         if (count > sizeof(struct sg_header)) {
 245             memcpy_tofs(buf,device->buff,count-sizeof(struct sg_header));
 246         }
 247     }
 248     else
 249         count=0;
 250     
 251     /*
 252      * Clean up, and release the device so that we can send another
 253      * command.
 254      */
 255     sg_free(device->buff,device->buff_len);
 256     device->buff = NULL;
 257     device->pending=0;
 258     wake_up(&device->write_wait);
 259     return count;
 260 }
 261 
 262 /*
 263  * This function is called by the interrupt handler when we
 264  * actually have a command that is complete.  Change the
 265  * flags to indicate that we have a result.
 266  */
 267 static void sg_command_done(Scsi_Cmnd * SCpnt)
     /* [previous][next][first][last][top][bottom][index][help] */
 268 {
 269     int dev = MINOR(SCpnt->request.rq_dev);
 270     struct scsi_generic *device = &scsi_generics[dev];
 271     if (!device->pending)
 272     {
 273         printk("unexpected done for sg %d\n",dev);
 274         SCpnt->request.rq_status = RQ_INACTIVE;
 275         return;
 276     }
 277 
 278     /*
 279      * See if the command completed normally, or whether something went
 280      * wrong.
 281      */
 282     memcpy(device->header.sense_buffer, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer));
 283     if (SCpnt->sense_buffer[0])
 284     {
 285         device->header.result=EIO;
 286     }
 287     else
 288         device->header.result=SCpnt->result;
 289 
 290     /*
 291      * Now wake up the process that is waiting for the
 292      * result.
 293      */
 294     device->complete=1;
 295     SCpnt->request.rq_status = RQ_INACTIVE;
 296     wake_up(&scsi_generics[dev].read_wait);
 297 }
 298 
 299 #define SG_SEND 0
 300 #define SG_REC  1
 301 
 302 static int sg_write(struct inode *inode,struct file *filp,const char *buf,int count)
     /* [previous][next][first][last][top][bottom][index][help] */
 303 {
 304     int                   bsize,size,amt,i;
 305     unsigned char         cmnd[MAX_COMMAND_SIZE];
 306     kdev_t                devt = inode->i_rdev;
 307     int                   dev = MINOR(devt);
 308     struct scsi_generic   * device=&scsi_generics[dev];
 309     int                   direction;
 310     unsigned char         opcode;
 311     Scsi_Cmnd           * SCpnt;
 312     
 313     if ((i=verify_area(VERIFY_READ,buf,count)))
 314         return i;
 315     /*
 316      * The minimum scsi command length is 6 bytes.  If we get anything
 317      * less than this, it is clearly bogus.  
 318      */
 319     if (count<(sizeof(struct sg_header) + 6))
 320         return -EIO;
 321 
 322     /*
 323      * If we still have a result pending from a previous command,
 324      * wait until the result has been read by the user before sending
 325      * another command.
 326      */
 327     while(device->pending)
 328     {
 329         if (filp->f_flags & O_NONBLOCK)
 330             return -EWOULDBLOCK;
 331 #ifdef DEBUG
 332         printk("sg_write: sleeping on pending request\n");
 333 #endif     
 334         interruptible_sleep_on(&device->write_wait);
 335         if (current->signal & ~current->blocked)
 336             return -ERESTARTSYS;
 337     }
 338 
 339     /*
 340      * Mark the device flags for the new state.
 341      */
 342     device->pending=1;
 343     device->complete=0;
 344     memcpy_fromfs(&device->header,buf,sizeof(struct sg_header));
 345 
 346     /*
 347      * fix input size, and see if we are sending data.
 348      */
 349     device->header.pack_len=count;
 350     buf+=sizeof(struct sg_header);
 351     if( device->header.pack_len > device->header.reply_len )
 352     {
 353         bsize = device->header.pack_len;
 354         direction = SG_SEND;
 355     } else {
 356         bsize = device->header.reply_len;
 357         direction = SG_REC;
 358     }
 359     
 360     /*
 361      * Don't include the command header itself in the size.
 362      */
 363     bsize-=sizeof(struct sg_header);
 364 
 365     /*
 366      * Allocate a buffer that is large enough to hold the data
 367      * that has been requested.  Round up to an even number of sectors,
 368      * since scsi_malloc allocates in chunks of 512 bytes.
 369      */
 370     amt=bsize;
 371     if (!bsize)
 372         bsize++;
 373     bsize=(bsize+511) & ~511;
 374 
 375     /*
 376      * If we cannot allocate the buffer, report an error.
 377      */
 378     if ((bsize<0) || !(device->buff=sg_malloc(device->buff_len=bsize)))
 379     {
 380         device->pending=0;
 381         wake_up(&device->write_wait);
 382         return -ENOMEM;
 383     }
 384 
 385 #ifdef DEBUG
 386     printk("allocating device\n");
 387 #endif
 388 
 389     /*
 390      * Grab a device pointer for the device we want to talk to.  If we
 391      * don't want to block, just return with the appropriate message.
 392      */
 393     if (!(SCpnt=allocate_device(NULL,device->device, !(filp->f_flags & O_NONBLOCK))))
 394     {
 395         device->pending=0;
 396         wake_up(&device->write_wait);
 397         sg_free(device->buff,device->buff_len);
 398         device->buff = NULL;
 399         return -EWOULDBLOCK;
 400     } 
 401 #ifdef DEBUG
 402     printk("device allocated\n");
 403 #endif    
 404 
 405     /*
 406      * Now we need to grab the command itself from the user's buffer.
 407      */
 408     SCpnt->request.rq_dev = devt;
 409     SCpnt->request.rq_status = RQ_ACTIVE;
 410     SCpnt->sense_buffer[0]=0;
 411     opcode = get_user(buf);
 412     size=COMMAND_SIZE(opcode);
 413     if (opcode >= 0xc0 && device->header.twelve_byte) size = 12;
 414     SCpnt->cmd_len = size;
 415 
 416     /*
 417      * If we are writing data, subtract off the size
 418      * of the command itself, to get the amount of actual data
 419      * that we need to send to the device.
 420      */
 421     if( direction == SG_SEND )
 422         amt -= size;
 423     
 424     /*
 425      * Verify that the user has actually passed enough bytes for this command.
 426      */
 427     if( count < (sizeof(struct sg_header) + size) )
 428     {
 429         device->pending=0;
 430         wake_up( &device->write_wait );
 431         sg_free( device->buff, device->buff_len );
 432         device->buff = NULL;
 433         return -EIO;
 434     }
 435     
 436     /*
 437      * Now copy the SCSI command from the user's address space.
 438      */
 439     memcpy_fromfs(cmnd,buf,size);
 440     buf+=size;
 441 
 442     /*
 443      * If we are writing data, copy the data we are writing.  The pack_len
 444      * field also includes the length of the header and the command,
 445      * so we need to subtract these off.
 446      */
 447     if( direction == SG_SEND )  memcpy_fromfs(device->buff,buf, amt);
 448     
 449     /*
 450      * Set the LUN field in the command structure.
 451      */
 452     cmnd[1]= (cmnd[1] & 0x1f) | (device->device->lun<<5);
 453 
 454 #ifdef DEBUG
 455     printk("do cmd\n");
 456 #endif
 457 
 458     /*
 459      * Now pass the actual command down to the low-level driver.  We
 460      * do not do any more here - when the interrupt arrives, we will
 461      * then do the post-processing.
 462      */
 463     scsi_do_cmd (SCpnt,(void *) cmnd,
 464                  (void *) device->buff,amt,
 465                  sg_command_done,device->timeout,SG_DEFAULT_RETRIES);
 466 
 467 #ifdef DEBUG
 468     printk("done cmd\n");
 469 #endif               
 470 
 471     return count;
 472 }
 473 
 474 static int sg_select(struct inode *inode, struct file *file, int sel_type, select_table * wait)
     /* [previous][next][first][last][top][bottom][index][help] */
 475 {
 476     int dev=MINOR(inode->i_rdev);
 477     int r = 0;
 478     struct scsi_generic *device=&scsi_generics[dev];
 479 
 480     if (sel_type == SEL_IN) {
 481         if(device->pending && device->complete)
 482         {
 483             r = 1;
 484         } else {
 485             select_wait(&scsi_generics[dev].read_wait, wait);
 486         }
 487     }
 488     if (sel_type == SEL_OUT) {
 489         if(!device->pending){
 490             r = 1;
 491         }
 492         else
 493         {
 494             select_wait(&scsi_generics[dev].write_wait, wait);
 495         }
 496     }
 497 
 498     return(r);
 499 }
 500 
 501 static struct file_operations sg_fops = {
 502     NULL,            /* lseek */
 503     sg_read,         /* read */
 504     sg_write,        /* write */
 505     NULL,            /* readdir */
 506     sg_select,       /* select */
 507     sg_ioctl,        /* ioctl */
 508     NULL,            /* mmap */
 509     sg_open,         /* open */
 510     sg_close,        /* release */
 511     NULL             /* fsync */
 512 };
 513 
 514 
 515 static int sg_detect(Scsi_Device * SDp){
     /* [previous][next][first][last][top][bottom][index][help] */
 516     ++sg_template.dev_noticed;
 517     return 1;
 518 }
 519 
 520 /* Driver initialization */
 521 static int sg_init()
     /* [previous][next][first][last][top][bottom][index][help] */
 522 {
 523     static int sg_registered = 0;
 524     
 525     if (sg_template.dev_noticed == 0) return 0;
 526     
 527     if(!sg_registered) {
 528         if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops)) 
 529         {
 530             printk("Unable to get major %d for generic SCSI device\n",
 531                    SCSI_GENERIC_MAJOR);
 532             return 1;
 533         }
 534         sg_registered++;
 535     }
 536     
 537     /* If we have already been through here, return */
 538     if(scsi_generics) return 0;
 539     
 540 #ifdef DEBUG
 541     printk("sg: Init generic device.\n");
 542 #endif
 543     
 544 #ifdef SG_BIG_BUFF
 545     big_buff= (char *) scsi_init_malloc(SG_BIG_BUFF, GFP_ATOMIC | GFP_DMA);
 546 #endif
 547     
 548     scsi_generics = (struct scsi_generic *) 
 549         scsi_init_malloc((sg_template.dev_noticed + SG_EXTRA_DEVS) 
 550                          * sizeof(struct scsi_generic), GFP_ATOMIC);
 551     memset(scsi_generics, 0, (sg_template.dev_noticed + SG_EXTRA_DEVS)
 552            * sizeof(struct scsi_generic));
 553     
 554     sg_template.dev_max = sg_template.dev_noticed + SG_EXTRA_DEVS;
 555     return 0;
 556 }
 557 
 558 static int sg_attach(Scsi_Device * SDp)
     /* [previous][next][first][last][top][bottom][index][help] */
 559 {
 560     struct scsi_generic * gpnt;
 561     int i;
 562     
 563     if(sg_template.nr_dev >= sg_template.dev_max) 
 564     {
 565         SDp->attached--;
 566         return 1;
 567     }
 568     
 569     for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++) 
 570         if(!gpnt->device) break;
 571     
 572     if(i >= sg_template.dev_max) panic ("scsi_devices corrupt (sg)");
 573     
 574     scsi_generics[i].device=SDp;
 575     scsi_generics[i].users=0;
 576     scsi_generics[i].generic_wait=NULL;
 577     scsi_generics[i].read_wait=NULL;
 578     scsi_generics[i].write_wait=NULL;
 579     scsi_generics[i].buff=NULL;
 580     scsi_generics[i].exclude=0;
 581     scsi_generics[i].pending=0;
 582     scsi_generics[i].timeout=SG_DEFAULT_TIMEOUT;
 583     sg_template.nr_dev++;
 584     return 0;
 585 };
 586 
 587 
 588 
 589 static void sg_detach(Scsi_Device * SDp)
     /* [previous][next][first][last][top][bottom][index][help] */
 590 {
 591     struct scsi_generic * gpnt;
 592     int i;
 593     
 594     for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++) 
 595         if(gpnt->device == SDp) {
 596             gpnt->device = NULL;
 597             SDp->attached--;
 598             sg_template.nr_dev--;
 599             return;
 600         }
 601     return;
 602 }
 603 
 604 #ifdef MODULE
 605 char kernel_version[] = UTS_RELEASE;
 606 
 607 int init_module(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 608     sg_template.usage_count = &mod_use_count_;
 609     return scsi_register_module(MODULE_SCSI_DEV, &sg_template);
 610 }
 611 
 612 void cleanup_module( void) 
     /* [previous][next][first][last][top][bottom][index][help] */
 613 {
 614     if (MOD_IN_USE) {
 615         printk(KERN_INFO __FILE__ ": module is in use, remove rejected\n");
 616         return;
 617     }
 618     scsi_unregister_module(MODULE_SCSI_DEV, &sg_template);
 619     unregister_chrdev(SCSI_GENERIC_MAJOR, "sg");
 620     
 621     if(scsi_generics != NULL) {
 622         scsi_init_free((char *) scsi_generics,
 623                        (sg_template.dev_noticed + SG_EXTRA_DEVS) 
 624                        * sizeof(struct scsi_generic));
 625     }
 626     sg_template.dev_max = 0;
 627 #ifdef SG_BIG_BUFF
 628     if(big_buff != NULL)
 629         scsi_init_free(big_buff, SG_BIG_BUFF);
 630 #endif
 631 }
 632 #endif /* MODULE */
 633 
 634 /*
 635  * Overrides for Emacs so that we almost follow Linus's tabbing style.
 636  * Emacs will notice this stuff at the end of the file and automatically
 637  * adjust the settings for this buffer only.  This must remain at the end
 638  * of the file.
 639  * ---------------------------------------------------------------------------
 640  * Local variables:
 641  * c-indent-level: 4
 642  * c-brace-imaginary-offset: 0
 643  * c-brace-offset: -4
 644  * c-argdecl-indent: 4
 645  * c-label-offset: -4
 646  * c-continued-statement-offset: 4
 647  * c-continued-brace-offset: 0
 648  * indent-tabs-mode: nil
 649  * tab-width: 8
 650  * End:
 651  */

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