This source file includes following definitions.
- count_dir_entries
 
- proc_lookupscsi
 
- proc_readscsidir
 
- get_not_present_info
 
- proc_readscsi
 
- proc_writescsi
 
- proc_scsilseek
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 #include <linux/autoconf.h>
  24 #include <asm/segment.h>
  25 #include <linux/errno.h>
  26 #include <linux/sched.h>
  27 #include <linux/proc_fs.h>
  28 #include <linux/stat.h>
  29 #include <linux/config.h>
  30 #include <linux/mm.h>
  31 
  32 
  33 static int proc_readscsi(struct inode * inode, struct file * file,
  34                          char * buf, int count);
  35 static int proc_writescsi(struct inode * inode, struct file * file,
  36                          const char * buf, int count);
  37 static int proc_readscsidir(struct inode *, struct file *, 
  38                             void *, filldir_t filldir);
  39 static int proc_lookupscsi(struct inode *,const char *,int,struct inode **);
  40 static int proc_scsilseek(struct inode *, struct file *, off_t, int);
  41 
  42 extern uint count_templates(void);
  43 extern void build_proc_dir_hba_entries(uint);
  44 
  45 
  46 extern int (* dispatch_scsi_info_ptr)(int, char *, char **, off_t, int, int);
  47     
  48     
  49 static struct file_operations proc_scsi_operations = {
  50     proc_scsilseek,     
  51     proc_readscsi,      
  52     proc_writescsi,     
  53     proc_readscsidir,   
  54     NULL,               
  55     NULL,               
  56     NULL,               
  57     NULL,               
  58     NULL,               
  59     NULL                
  60 };
  61 
  62 
  63 
  64 
  65 struct inode_operations proc_scsi_inode_operations = {
  66     &proc_scsi_operations,  
  67     NULL,           
  68     proc_lookupscsi,
  69     NULL,           
  70     NULL,           
  71     NULL,           
  72     NULL,           
  73     NULL,           
  74     NULL,           
  75     NULL,           
  76     NULL,           
  77     NULL,           
  78     NULL,           
  79     NULL,           
  80     NULL            
  81 };
  82 
  83 struct proc_dir_entry scsi_dir[PROC_SCSI_FILE - PROC_SCSI_SCSI + 3]; 
  84 struct proc_dir_entry scsi_hba_dir[(PROC_SCSI_LAST - PROC_SCSI_FILE) * 4]; 
  85 
  86 static struct proc_dir_entry scsi_dir2[] = {
  87     { PROC_SCSI,                 1, "." },
  88     { PROC_ROOT_INO,             2, ".." },
  89     { PROC_SCSI_NOT_PRESENT,    11, "not.present" },
  90     { 0, 0, NULL }
  91 };
  92 
  93 inline static uint count_dir_entries(uint inode, uint *num)
     
  94 {
  95     struct proc_dir_entry *dir;
  96     uint index, flag;
  97 
  98     (uint) *num = flag = index = 0;    
  99     
 100     if(dispatch_scsi_info_ptr) {
 101         if (inode == PROC_SCSI) { 
 102             dir = scsi_dir;
 103             while(dir[(uint)*num].low_ino)
 104                 (*num)++;
 105         } else {
 106             
 107 
 108 
 109 
 110 
 111             dir = scsi_hba_dir;
 112             while(dir[index].low_ino || dir[index].low_ino <= PROC_SCSI_LAST) {
 113                 if(dir[index].low_ino == inode)
 114                     flag = 1;
 115                 if(dir[index].low_ino == 0) {
 116                     if(flag == 1)
 117                         break;
 118                     else
 119                         *num = 0;
 120                 } else {
 121                     (*num)++;
 122                 }
 123                 index++;
 124             }
 125             return(index - (*num));
 126         }
 127     }
 128     else {
 129         dir = scsi_dir2;
 130         while(dir[(uint)*num].low_ino)
 131             (*num)++;
 132     }   
 133     return(0);
 134 }
 135 
 136 static int proc_lookupscsi(struct inode * dir, const char * name, int len,
     
 137                            struct inode ** result)
 138 {
 139     struct proc_dir_entry *de = NULL;
 140 
 141     *result = NULL;
 142     if (!dir)
 143         return(-ENOENT);
 144     if (!S_ISDIR(dir->i_mode)) {
 145         iput(dir);
 146         return(-ENOENT);
 147     }
 148     if (dispatch_scsi_info_ptr != NULL) {
 149         if (dir->i_ino <= PROC_SCSI_SCSI)
 150             de = scsi_dir;
 151         else {
 152             de = &scsi_hba_dir[dispatch_scsi_info_ptr(dir->i_ino, 0, 0, 0, 0, 2)];
 153         }
 154     }
 155     else
 156         de = scsi_dir2;
 157     
 158     for (; de->name ; de++) {
 159         if (!proc_match(len, name, de))
 160             continue;
 161         *result = iget(dir->i_sb, de->low_ino);
 162         iput(dir);
 163         if (!*result)
 164             return(-ENOENT);
 165         return(0);
 166     }
 167     iput(dir);
 168     return(-ENOENT);
 169 }
 170 
 171 static int proc_readscsidir(struct inode * inode, struct file * filp,
     
 172                             void * dirent, filldir_t filldir)
 173 {
 174     struct proc_dir_entry * de;
 175     uint index, num;
 176  
 177     num = 0;
 178 
 179     if (!inode || !S_ISDIR(inode->i_mode))
 180         return(-EBADF);
 181 
 182     index = count_dir_entries(inode->i_ino, &num);
 183 
 184     while (((unsigned) filp->f_pos + index) < index + num) {
 185         if (dispatch_scsi_info_ptr) {
 186             if (inode->i_ino <= PROC_SCSI_SCSI)
 187                 de = scsi_dir + filp->f_pos;
 188             else
 189                 de = scsi_hba_dir + filp->f_pos + index;
 190         }
 191         else {
 192             de = scsi_dir2 + filp->f_pos;
 193         }
 194         if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino)<0)
 195             break;
 196         filp->f_pos++;
 197     }
 198     return(0);
 199 }
 200 
 201 int get_not_present_info(char *buffer, char **start, off_t offset, int length)
     
 202 {
 203     int len, pos, begin;
 204     
 205     begin = 0;
 206     pos = len = sprintf(buffer, 
 207                         "No low-level scsi modules are currently present\n");
 208     if(pos < offset) {
 209         len = 0;
 210         begin = pos;
 211     }
 212     
 213     *start = buffer + (offset - begin);   
 214     len -= (offset - begin);
 215     if(len > length)
 216         len = length;
 217     
 218     return(len);
 219 }
 220 
 221 #define PROC_BLOCK_SIZE (3*1024)     
 222 
 223 
 224 
 225 static int proc_readscsi(struct inode * inode, struct file * file,
     
 226                          char * buf, int count)
 227 {
 228     int length;
 229     int bytes = count;
 230     int copied = 0;
 231     int thistime;
 232     char * page;
 233     char * start;
 234     
 235     if (count < -1)                
 236         return(-EINVAL);          
 237 
 238 
 239     if (!(page = (char *) __get_free_page(GFP_KERNEL)))
 240         return(-ENOMEM);
 241     
 242     while(bytes > 0 || count == -1) {   
 243         thistime = bytes;
 244         if(bytes > PROC_BLOCK_SIZE || count == -1)
 245             thistime = PROC_BLOCK_SIZE;
 246         
 247         if(dispatch_scsi_info_ptr)
 248             length = dispatch_scsi_info_ptr(inode->i_ino, page, &start, 
 249                                             file->f_pos, thistime, 0);
 250         else
 251             length = get_not_present_info(page, &start, file->f_pos, thistime);
 252         if(length < 0) {
 253             free_page((ulong) page);
 254             return(length);
 255         }
 256         
 257         
 258 
 259 
 260 
 261 
 262         if (length <= 0)
 263             break;
 264         
 265 
 266 
 267 
 268         if (count != -1)
 269             memcpy_tofs(buf + copied, start, length);
 270         file->f_pos += length;  
 271         bytes -= length;
 272         copied += length;
 273         
 274         if(length < thistime)
 275             break;  
 276         
 277     }
 278     
 279     free_page((ulong) page);
 280     return(copied);
 281 }
 282 
 283 
 284 static int proc_writescsi(struct inode * inode, struct file * file,
     
 285                          const char * buf, int count)
 286 {
 287     int ret = 0;
 288     char * page;
 289     
 290     if (!(page = (char *) __get_free_page(GFP_KERNEL)))
 291         return(-ENOMEM);
 292 
 293     if(count > PROC_BLOCK_SIZE) {
 294         return(-EOVERFLOW);
 295     }
 296 
 297     if(dispatch_scsi_info_ptr != NULL) {
 298         memcpy_fromfs(page, buf, count);
 299         ret = dispatch_scsi_info_ptr(inode->i_ino, page, 0, 0, count, 1);
 300     } else {
 301         free_page((ulong) page);   
 302         return(-ENOPKG);          
 303     }
 304     
 305     free_page((ulong) page);
 306     return(ret);
 307 }
 308 
 309 
 310 static int proc_scsilseek(struct inode * inode, struct file * file, 
     
 311                           off_t offset, int orig)
 312 {
 313     switch (orig) {
 314     case 0:
 315         file->f_pos = offset;
 316         return(file->f_pos);
 317     case 1:
 318         file->f_pos += offset;
 319         return(file->f_pos);
 320     case 2:                  
 321         if (offset)          
 322             return(-EINVAL);  
 323         proc_readscsi(inode, file, 0, -1);  
 324         return(file->f_pos);
 325     default:
 326         return(-EINVAL);
 327     }
 328 }
 329 
 330 
 331 
 332 
 333 
 334 
 335 
 336 
 337 
 338 
 339 
 340 
 341 
 342 
 343 
 344 
 345 
 346 
 347