root/drivers/scsi/scsi_proc.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_hba_index
  2. generic_proc_info
  3. dispatch_scsi_info
  4. count_templates
  5. build_proc_dir_hba_entries
  6. build_proc_dir_entries
  7. parseFree
  8. parseInit
  9. parseOpt

   1 /*
   2  * linux/drivers/scsi/scsi_proc.c
   3  *
   4  * The functions in this file provide an interface between
   5  * the PROC file system and the SCSI device drivers
   6  * It is mainly used for debugging, statistics and to pass 
   7  * information directly to the lowlevel driver.
   8  *
   9  * (c) 1995 Michael Neuffer neuffer@goofy.zdv.uni-mainz.de 
  10  * Version: 0.99.5   last change: 95/06/28
  11  * 
  12  * generic command parser provided by: 
  13  * Andreas Heilwagen <crashcar@informatik.uni-koblenz.de>
  14  */
  15 
  16 
  17 #include <linux/string.h>
  18 #include <linux/mm.h>
  19 #include <linux/malloc.h>
  20 #include <linux/proc_fs.h>
  21 #include <linux/errno.h>
  22 #include "../block/blk.h"
  23 #include "scsi.h"
  24 #include "hosts.h"
  25 
  26 #ifndef TRUE
  27 #define TRUE  1
  28 #define FALSE 0
  29 #endif
  30 
  31 extern struct proc_dir_entry scsi_dir[];
  32 extern struct proc_dir_entry scsi_hba_dir[];
  33 extern int scsi_proc_info(char *, char **, off_t, int, int, int);
  34  
  35 
  36 int get_hba_index(int ino)
     /* [previous][next][first][last][top][bottom][index][help] */
  37 {
  38     Scsi_Host_Template *tpnt = scsi_hosts;
  39     struct Scsi_Host *hpnt = scsi_hostlist;
  40     uint x = 0;
  41 
  42     while (tpnt) {
  43         if (ino == tpnt->low_ino) 
  44                 return(x);
  45         x += 3;
  46         while (hpnt) {
  47             hpnt = hpnt->next;
  48             x++;
  49         }
  50         tpnt = tpnt->next;
  51     }
  52     return(0);
  53 }
  54 
  55 /* generic_proc_info
  56  * Used if the driver currently has no own support for /proc/scsi
  57  */
  58 int generic_proc_info(char *buffer, char **start, off_t offset, 
     /* [previous][next][first][last][top][bottom][index][help] */
  59                      int length, int inode, int inout)
  60 {
  61     int len, pos, begin;
  62 
  63     if(inout == TRUE)
  64         return(-ENOSYS);  /* This is a no-op */
  65     
  66     begin = 0;
  67     pos = len = sprintf(buffer, 
  68                         "The driver does not yet support the proc-fs\n");
  69     if(pos < offset)
  70     {
  71         len = 0;
  72         begin = pos;
  73     }
  74     
  75     *start = buffer + (offset - begin);   /* Start of wanted data */
  76     len -= (offset - begin);
  77     if(len > length)
  78         len = length;
  79     
  80     return(len);
  81 }
  82 
  83 /* dispatch_scsi_info is the central dispatcher 
  84  * It is the interface between the proc-fs and the SCSI subsystem code
  85  */
  86 extern int dispatch_scsi_info(int ino, char *buffer, char **start, 
     /* [previous][next][first][last][top][bottom][index][help] */
  87                               off_t offset, int length, int func)
  88 {
  89     struct Scsi_Host *hpnt = scsi_hostlist;
  90 
  91     if(func != 2) {    
  92         if(ino == PROC_SCSI_SCSI) 
  93             return(scsi_proc_info(buffer, start, offset, length, 
  94                                   hpnt->host_no, func));
  95         while(hpnt) {
  96             if (ino == (hpnt->host_no + PROC_SCSI_FILE)) 
  97                 return(hpnt->hostt->proc_info(buffer, start, offset, length, 
  98                                               hpnt->host_no, func));
  99             hpnt = hpnt->next;
 100         }
 101         return(-EBADF);
 102     } else
 103         return(get_hba_index(ino));
 104 }
 105 
 106 inline uint count_templates(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 107 {
 108     Scsi_Host_Template *tpnt = scsi_hosts;
 109     uint x = 0;
 110     
 111     while (tpnt) {
 112         tpnt = tpnt->next;
 113         x++;
 114     }
 115     return (x);
 116 }
 117 
 118 void build_proc_dir_hba_entries(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 119 {
 120     Scsi_Host_Template *tpnt = scsi_hosts;
 121     struct Scsi_Host *hpnt = scsi_hostlist;
 122     static char names[PROC_SCSI_LAST - PROC_SCSI_FILE][3];
 123     uint x, y;
 124     
 125     x = y = 0;
 126 
 127     while (tpnt) {
 128         scsi_hba_dir[x].low_ino = tpnt->low_ino;
 129         scsi_hba_dir[x].namelen = 1;
 130         scsi_hba_dir[x++].name = ".";
 131         scsi_hba_dir[x].low_ino = PROC_SCSI;
 132         scsi_hba_dir[x].namelen = 2;
 133         scsi_hba_dir[x++].name = "..";
 134             
 135         while (hpnt) {
 136             if (tpnt == hpnt->hostt) {
 137                 scsi_hba_dir[x].low_ino = PROC_SCSI_FILE + hpnt->host_no;
 138                 scsi_hba_dir[x].namelen = sprintf(names[y],"%d",hpnt->host_no);
 139                 scsi_hba_dir[x].name = names[y];
 140                 y++;
 141                 x++;
 142             }
 143             hpnt = hpnt->next;
 144         }
 145         
 146         scsi_hba_dir[x].low_ino = 0;
 147         scsi_hba_dir[x].namelen = 0;
 148         scsi_hba_dir[x++].name = NULL;
 149         tpnt = tpnt->next;
 150     }    
 151 }
 152 
 153 void build_proc_dir_entries(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 154 {
 155     Scsi_Host_Template *tpnt = scsi_hosts;
 156     
 157     uint newnum; 
 158     uint x;
 159     
 160     newnum = count_templates();
 161     
 162     scsi_dir[0].low_ino = PROC_SCSI;
 163     scsi_dir[0].namelen = 1;
 164     scsi_dir[0].name = ".";
 165     scsi_dir[1].low_ino = PROC_ROOT_INO;
 166     scsi_dir[1].namelen = 2;
 167     scsi_dir[1].name = "..";
 168     scsi_dir[2].low_ino = PROC_SCSI_SCSI;
 169     scsi_dir[2].namelen = 4;
 170     scsi_dir[2].name = "scsi";
 171     for(x = 3; x < newnum + 3; x++, tpnt = tpnt->next) {
 172         scsi_dir[x].low_ino = tpnt->low_ino;
 173         scsi_dir[x].namelen = strlen(tpnt->procname);
 174         scsi_dir[x].name = tpnt->procname;
 175     }
 176     scsi_dir[x].low_ino = 0;
 177     scsi_dir[x].namelen = 0;
 178     scsi_dir[x].name = NULL;
 179     
 180     build_proc_dir_hba_entries();
 181 }
 182 
 183 
 184 /*
 185  *  parseHandle *parseInit(char *buf, char *cmdList, int cmdNum); 
 186  *              gets a pointer to a null terminated data buffer
 187  *              and a list of commands with blanks as delimiter 
 188  *      in between. 
 189  *      The commands have to be alphanumerically sorted. 
 190  *      cmdNum has to contain the number of commands.
 191  *              On success, a pointer to a handle structure
 192  *              is returned, NULL on failure
 193  *
 194  *      int parseOpt(parseHandle *handle, char **param);
 195  *              processes the next parameter. On success, the
 196  *              index of the appropriate command in the cmdList
 197  *              is returned, starting with zero.
 198  *              param points to the null terminated parameter string.
 199  *              On failure, -1 is returned.
 200  *
 201  *      The databuffer buf may only contain pairs of commands
 202  *          options, separated by blanks:
 203  *              <Command> <Parameter> [<Command> <Parameter>]*
 204  */
 205 
 206 typedef struct
 207 {
 208     char *buf,                             /* command buffer  */
 209          *cmdList,                         /* command list    */
 210          *bufPos,                          /* actual position */
 211          **cmdPos,                         /* cmdList index   */
 212          cmdNum;                           /* cmd number      */
 213 } parseHandle;
 214         
 215 
 216 inline int parseFree (parseHandle *handle)               /* free memory     */
     /* [previous][next][first][last][top][bottom][index][help] */
 217 {
 218     kfree (handle->cmdPos);
 219     kfree (handle);
 220     
 221     return(-1);
 222 }
 223 
 224         
 225 parseHandle *parseInit(char *buf, char *cmdList, int cmdNum)
     /* [previous][next][first][last][top][bottom][index][help] */
 226 {
 227     char        *ptr;                               /* temp pointer    */
 228     parseHandle *handle;                            /* new handle      */
 229     
 230     if (!buf || !cmdList)                           /* bad input ?     */
 231         return(NULL);
 232     if ((handle = (parseHandle*) kmalloc(sizeof(parseHandle), 1)) == 0)
 233         return(NULL);                               /* out of memory   */
 234     if ((handle->cmdPos = (char**) kmalloc(sizeof(int), cmdNum)) == 0) {
 235         kfree(handle);
 236         return(NULL);                               /* out of memory   */
 237     }
 238     
 239     handle->buf     = handle->bufPos = buf;         /* init handle     */
 240     handle->cmdList = cmdList;
 241     handle->cmdNum  = cmdNum;
 242     
 243     handle->cmdPos[cmdNum = 0] = cmdList;
 244     for (ptr = cmdList; *ptr; ptr++) {          /* scan command string */
 245         if(*ptr == ' ') {                       /* and insert zeroes   */
 246             *ptr++ = 0;
 247             handle->cmdPos[++cmdNum] = ptr++;
 248         } 
 249     }
 250     return(handle);
 251 }
 252 
 253 
 254 int parseOpt(parseHandle *handle, char **param)
     /* [previous][next][first][last][top][bottom][index][help] */
 255 {
 256     int  cmdIndex = 0, 
 257          cmdLen = 0;
 258     char *startPos;
 259     
 260     if (!handle)                                    /* invalid handle  */
 261         return(parseFree(handle));
 262     /* skip spaces     */  
 263     for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++);
 264     if (!*(handle->bufPos))
 265         return(parseFree(handle));                  /* end of data     */
 266     
 267     startPos = handle->bufPos;                      /* store cmd start */
 268     for (; handle->cmdPos[cmdIndex][cmdLen] && *(handle->bufPos); handle->bufPos++)
 269     {                                               /* no string end?  */
 270         for (;;)
 271         {
 272             if (*(handle->bufPos) == handle->cmdPos[cmdIndex][cmdLen])
 273                 break;                              /* char matches ?  */
 274             else
 275                 if (memcmp(startPos, (char*)(handle->cmdPos[++cmdIndex]), cmdLen))
 276                     return(parseFree(handle));      /* unknown command */
 277             
 278             if (cmdIndex >= handle->cmdNum)
 279                 return(parseFree(handle));          /* unknown command */     
 280         }
 281         
 282         cmdLen++;                                   /* next char       */
 283     }
 284     
 285     /* Get param. First skip all blanks, then insert zero after param  */
 286     
 287     for (; *(handle->bufPos) && *(handle->bufPos) == ' '; handle->bufPos++);
 288     *param = handle->bufPos; 
 289     
 290     for (; *(handle->bufPos) && *(handle->bufPos) != ' '; handle->bufPos++);
 291     *(handle->bufPos++) = 0;
 292     
 293     return(cmdIndex);
 294 }
 295 
 296 
 297 /*
 298  * Overrides for Emacs so that we get a uniform tabbing style.
 299  * Emacs will notice this stuff at the end of the file and automatically
 300  * adjust the settings for this buffer only.  This must remain at the end
 301  * of the file.
 302  * ---------------------------------------------------------------------------
 303  * Local variables:
 304  * c-indent-level: 4
 305  * c-brace-imaginary-offset: 0
 306  * c-brace-offset: -4
 307  * c-argdecl-indent: 4
 308  * c-label-offset: -4
 309  * c-continued-statement-offset: 4
 310  * c-continued-brace-offset: 0
 311  * indent-tabs-mode: nil
 312  * tab-width: 8
 313  * End:
 314  */

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