root/kernel/blk_drv/scsi/scsi_ioctl.c

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

DEFINITIONS

This source file includes following definitions.
  1. ioctl_probe
  2. scsi_ioctl_done
  3. ioctl_command
  4. scsi_ioctl

   1 #include <linux/config.h>
   2 #ifdef CONFIG_SCSI 
   3 
   4 #include <errno.h>
   5 #include <asm/io.h>
   6 #include <asm/segment.h>
   7 #include <asm/system.h>
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/sched.h>
  11 #include <linux/string.h>
  12 
  13 #include "scsi.h"
  14 #include "hosts.h"
  15 #include "scsi_ioctl.h"
  16 
  17 #define MAX_RETRIES 5   
  18 #define MAX_TIMEOUT 200
  19 #define MAX_BUF 1024    
  20 
  21 #define max(a,b) (((a) > (b)) ? (a) : (b))
  22 
  23 /*
  24  * If we are told to probe a host, we will return 0 if  the host is not
  25  * present, 1 if the host is present, and will return an identifying
  26  * string at *arg, if arg is non null, filling to the length stored at
  27  * (int *) arg
  28  */
  29 
  30 static int ioctl_probe(int dev, void *buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
  31 {
  32         int temp;
  33         int len;
  34         
  35         if ((temp = scsi_hosts[dev].present) && buffer) {
  36                 len = get_fs_long ((int *) buffer);
  37                 memcpy_tofs (buffer, scsi_hosts[dev].info(), len);
  38         }
  39         return temp;
  40 }
  41 
  42 /*
  43  * 
  44  * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host.
  45  * The MAX_TIMEOUT and MAX_RETRIES  variables are used.  
  46  * 
  47  * dev is the SCSI device number, *(int *) arg the length of the input
  48  * data, *((int *)arg + 1) the output buffer.
  49  * 
  50  * *(char *) ((int *) arg)[1] the actual command.   
  51  * 
  52  * Note that no more than MAX_BUF bytes will be transfered.  Since
  53  * SCSI block device size is 512 bytes, I figured 1K was good.
  54  * 
  55  * This size * does  * include  the initial lengths that were passed.
  56  * 
  57  * The SCSI command is read from  the memory location immediately after the
  58  * length words, and the out data after the command.  The SCSI routines know the
  59  * command size based on the length byte.  
  60  * 
  61  * The area is then filled in from the byte at offset 0. 
  62  */
  63 
  64 static int the_result[MAX_SCSI_HOSTS];
  65 
  66 static void scsi_ioctl_done (int host, int result)
     /* [previous][next][first][last][top][bottom][index][help] */
  67 {
  68         the_result[host] = result;      
  69 }       
  70         
  71 static int ioctl_command(Scsi_Device *dev, void *buffer)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73         char buf[MAX_BUF];
  74         char cmd[10];
  75         char * cmd_in;
  76         unsigned char opcode;
  77         int inlen, outlen, cmdlen, temp, host;
  78 
  79         if (!buffer)
  80                 return -EINVAL;
  81         
  82         inlen = get_fs_long((int *) buffer);
  83         outlen = get_fs_long(((int *) buffer) + 1);
  84 
  85         cmd_in = (char *) ( ((int *)buffer) + 2);
  86         opcode = get_fs_byte(cmd_in); 
  87 
  88         memcpy_fromfs ((void *) cmd,  cmd_in, cmdlen = COMMAND_SIZE (opcode));
  89         memcpy_fromfs ((void *) buf,  (void *) (cmd_in + cmdlen), inlen);
  90         host = dev->host_no;
  91 
  92 #ifndef DEBUG_NO_CMD
  93         do {
  94                 cli();
  95                 if (the_result[host]) {
  96                         sti();
  97                         while(the_result[host])
  98                                 /* nothing */;
  99                 } else {
 100                         the_result[host]=-1;
 101                         sti();
 102                         break;
 103                 }
 104         } while (1);
 105         
 106         scsi_do_cmd(host,  dev->id, cmd, buf, ((outlen > MAX_BUF) ? 
 107                         MAX_BUF : outlen),  scsi_ioctl_done, MAX_TIMEOUT, 
 108                         buf, MAX_RETRIES);
 109 
 110         while (the_result[host] == -1)
 111                 /* nothing */;
 112         temp = the_result[host];
 113         the_result[host]=0;
 114         memcpy_tofs (buffer, buf, (outlen > MAX_BUF) ? MAX_BUF  : outlen);
 115         return temp;
 116 #else
 117         {
 118         int i;
 119         printk("scsi_ioctl : device %d.  command = ", dev);
 120         for (i = 0; i < 10; ++i)
 121                 printk("%02x ", cmd[i]);
 122         printk("\r\nbuffer =");
 123         for (i = 0; i < 20; ++i)
 124                 printk("%02x ", buf[i]);
 125         printk("\r\n");
 126         }
 127         return 0;
 128 #endif
 129 }
 130 
 131         
 132 /*
 133         the scsi_ioctl() function differs from most ioctls in that it does
 134         not take a major/minor number as the dev filed.  Rather, it takes
 135         an index in scsi_devices[] 
 136 */
 137 int scsi_ioctl (int dev, int cmd, void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 138 {
 139         if ((cmd != 0 && dev > NR_SCSI_DEVICES) || dev < 0)
 140                 return -ENODEV;
 141         if ((cmd == 0 && dev > MAX_SCSI_HOSTS))
 142                 return -ENODEV;
 143         
 144         switch (cmd) {
 145                 case SCSI_IOCTL_PROBE_HOST:
 146                         return ioctl_probe(dev, arg);
 147                 case SCSI_IOCTL_SEND_COMMAND:
 148                         return ioctl_command((Scsi_Device *) dev, arg);
 149                 default :                       
 150                         return -EINVAL;
 151         }
 152 }
 153 #endif

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