home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / scsi / sg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-19  |  11.5 KB  |  442 lines

  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,
  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)
  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)
  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)
  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) 
  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)
  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)
  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)
  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){
  339.   ++sg_template.dev_noticed;
  340.   return 1;
  341. }
  342.  
  343. /* Driver initialization */
  344. static void sg_init()
  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)
  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)
  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.  */
  442.