home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / fs / devices.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-03  |  5.9 KB  |  269 lines

  1. /*
  2.  *  linux/fs/devices.c
  3.  *
  4.  * (C) 1993 Matthias Urlichs -- collected common code and tables.
  5.  * 
  6.  *  Copyright (C) 1991, 1992  Linus Torvalds
  7.  */
  8.  
  9. #include <linux/fs.h>
  10. #include <linux/major.h>
  11. #include <linux/string.h>
  12. #include <linux/sched.h>
  13. #include <linux/ext_fs.h>
  14. #include <linux/stat.h>
  15. #include <linux/fcntl.h>
  16. #include <linux/errno.h>
  17.  
  18. struct device_struct {
  19.     const char * name;
  20.     struct file_operations * fops;
  21. };
  22.  
  23. static struct device_struct chrdevs[MAX_CHRDEV] = {
  24.     { NULL, NULL },
  25. };
  26.  
  27. static struct device_struct blkdevs[MAX_BLKDEV] = {
  28.     { NULL, NULL },
  29. };
  30.  
  31. int get_device_list(char * page)
  32. {
  33.     int i;
  34.     int len;
  35.  
  36.     len = sprintf(page, "Character devices:\n");
  37.     for (i = 0; i < MAX_CHRDEV ; i++) {
  38.         if (chrdevs[i].fops) {
  39.             len += sprintf(page+len, "%2d %s\n", i, chrdevs[i].name);
  40.         }
  41.     }
  42.     len += sprintf(page+len, "\nBlock devices:\n");
  43.     for (i = 0; i < MAX_BLKDEV ; i++) {
  44.         if (blkdevs[i].fops) {
  45.             len += sprintf(page+len, "%2d %s\n", i, blkdevs[i].name);
  46.         }
  47.     }
  48.     return len;
  49. }
  50.  
  51. struct file_operations * get_blkfops(unsigned int major)
  52. {
  53.     if (major >= MAX_BLKDEV)
  54.         return NULL;
  55.     return blkdevs[major].fops;
  56. }
  57.  
  58. struct file_operations * get_chrfops(unsigned int major)
  59. {
  60.     if (major >= MAX_CHRDEV)
  61.         return NULL;
  62.     return chrdevs[major].fops;
  63. }
  64.  
  65. int register_chrdev(unsigned int major, const char * name, struct file_operations *fops)
  66. {
  67.     if (major == 0) {
  68.         for (major = MAX_CHRDEV-1; major > 0; major--) {
  69.             if (chrdevs[major].fops == NULL) {
  70.                 chrdevs[major].name = name;
  71.                 chrdevs[major].fops = fops;
  72.                 return major;
  73.             }
  74.         }
  75.         return -EBUSY;
  76.     }
  77.     if (major >= MAX_CHRDEV)
  78.         return -EINVAL;
  79.     if (chrdevs[major].fops && chrdevs[major].fops != fops)
  80.         return -EBUSY;
  81.     chrdevs[major].name = name;
  82.     chrdevs[major].fops = fops;
  83.     return 0;
  84. }
  85.  
  86. int register_blkdev(unsigned int major, const char * name, struct file_operations *fops)
  87. {
  88.     if (major == 0) {
  89.         for (major = MAX_BLKDEV-1; major > 0; major--) {
  90.             if (blkdevs[major].fops == NULL) {
  91.                 blkdevs[major].name = name;
  92.                 blkdevs[major].fops = fops;
  93.                 return major;
  94.             }
  95.         }
  96.         return -EBUSY;
  97.     }
  98.     if (major >= MAX_BLKDEV)
  99.         return -EINVAL;
  100.     if (blkdevs[major].fops && blkdevs[major].fops != fops)
  101.         return -EBUSY;
  102.     blkdevs[major].name = name;
  103.     blkdevs[major].fops = fops;
  104.     return 0;
  105. }
  106.  
  107. int unregister_chrdev(unsigned int major, const char * name)
  108. {
  109.     if (major >= MAX_CHRDEV)
  110.         return -EINVAL;
  111.     if (!chrdevs[major].fops)
  112.         return -EINVAL;
  113.     if (strcmp(chrdevs[major].name, name))
  114.         return -EINVAL;
  115.     chrdevs[major].name = NULL;
  116.     chrdevs[major].fops = NULL;
  117.     return 0;
  118. }
  119.  
  120. int unregister_blkdev(unsigned int major, const char * name)
  121. {
  122.     if (major >= MAX_BLKDEV)
  123.         return -EINVAL;
  124.     if (!blkdevs[major].fops)
  125.         return -EINVAL;
  126.     if (strcmp(blkdevs[major].name, name))
  127.         return -EINVAL;
  128.     blkdevs[major].name = NULL;
  129.     blkdevs[major].fops = NULL;
  130.     return 0;
  131. }
  132.  
  133. /*
  134.  * This routine checks whether a removable media has been changed,
  135.  * and invalidates all buffer-cache-entries in that case. This
  136.  * is a relatively slow routine, so we have to try to minimize using
  137.  * it. Thus it is called only upon a 'mount' or 'open'. This
  138.  * is the best way of combining speed and utility, I think.
  139.  * People changing diskettes in the middle of an operation deserve
  140.  * to loose :-)
  141.  */
  142. int check_disk_change(dev_t dev)
  143. {
  144.     int i;
  145.     struct file_operations * fops;
  146.  
  147.     i = MAJOR(dev);
  148.     if (i >= MAX_BLKDEV || (fops = blkdevs[i].fops) == NULL)
  149.         return 0;
  150.     if (fops->check_media_change == NULL)
  151.         return 0;
  152.     if (!fops->check_media_change(dev))
  153.         return 0;
  154.  
  155.     printk("VFS: Disk change detected on device %d/%d\n",
  156.                     MAJOR(dev), MINOR(dev));
  157.     for (i=0 ; i<NR_SUPER ; i++)
  158.         if (super_blocks[i].s_dev == dev)
  159.             put_super(super_blocks[i].s_dev);
  160.     invalidate_inodes(dev);
  161.     invalidate_buffers(dev);
  162.  
  163.     if (fops->revalidate)
  164.         fops->revalidate(dev);
  165.     return 1;
  166. }
  167.  
  168. /*
  169.  * Called every time a block special file is opened
  170.  */
  171. int blkdev_open(struct inode * inode, struct file * filp)
  172. {
  173.     int i;
  174.  
  175.     i = MAJOR(inode->i_rdev);
  176.     if (i >= MAX_BLKDEV || !blkdevs[i].fops)
  177.         return -ENODEV;
  178.     filp->f_op = blkdevs[i].fops;
  179.     if (filp->f_op->open)
  180.         return filp->f_op->open(inode,filp);
  181.     return 0;
  182. }    
  183.  
  184. /*
  185.  * Dummy default file-operations: the only thing this does
  186.  * is contain the open that then fills in the correct operations
  187.  * depending on the special file...
  188.  */
  189. struct file_operations def_blk_fops = {
  190.     NULL,        /* lseek */
  191.     NULL,        /* read */
  192.     NULL,        /* write */
  193.     NULL,        /* readdir */
  194.     NULL,        /* select */
  195.     NULL,        /* ioctl */
  196.     NULL,        /* mmap */
  197.     blkdev_open,    /* open */
  198.     NULL,        /* release */
  199. };
  200.  
  201. struct inode_operations blkdev_inode_operations = {
  202.     &def_blk_fops,        /* default file operations */
  203.     NULL,            /* create */
  204.     NULL,            /* lookup */
  205.     NULL,            /* link */
  206.     NULL,            /* unlink */
  207.     NULL,            /* symlink */
  208.     NULL,            /* mkdir */
  209.     NULL,            /* rmdir */
  210.     NULL,            /* mknod */
  211.     NULL,            /* rename */
  212.     NULL,            /* readlink */
  213.     NULL,            /* follow_link */
  214.     NULL,            /* bmap */
  215.     NULL,            /* truncate */
  216.     NULL            /* permission */
  217. };
  218.  
  219. /*
  220.  * Called every time a character special file is opened
  221.  */
  222. int chrdev_open(struct inode * inode, struct file * filp)
  223. {
  224.     int i;
  225.  
  226.     i = MAJOR(inode->i_rdev);
  227.     if (i >= MAX_CHRDEV || !chrdevs[i].fops)
  228.         return -ENODEV;
  229.     filp->f_op = chrdevs[i].fops;
  230.     if (filp->f_op->open)
  231.         return filp->f_op->open(inode,filp);
  232.     return 0;
  233. }
  234.  
  235. /*
  236.  * Dummy default file-operations: the only thing this does
  237.  * is contain the open that then fills in the correct operations
  238.  * depending on the special file...
  239.  */
  240. struct file_operations def_chr_fops = {
  241.     NULL,        /* lseek */
  242.     NULL,        /* read */
  243.     NULL,        /* write */
  244.     NULL,        /* readdir */
  245.     NULL,        /* select */
  246.     NULL,        /* ioctl */
  247.     NULL,        /* mmap */
  248.     chrdev_open,    /* open */
  249.     NULL,        /* release */
  250. };
  251.  
  252. struct inode_operations chrdev_inode_operations = {
  253.     &def_chr_fops,        /* default file operations */
  254.     NULL,            /* create */
  255.     NULL,            /* lookup */
  256.     NULL,            /* link */
  257.     NULL,            /* unlink */
  258.     NULL,            /* symlink */
  259.     NULL,            /* mkdir */
  260.     NULL,            /* rmdir */
  261.     NULL,            /* mknod */
  262.     NULL,            /* rename */
  263.     NULL,            /* readlink */
  264.     NULL,            /* follow_link */
  265.     NULL,            /* bmap */
  266.     NULL,            /* truncate */
  267.     NULL            /* permission */
  268. };
  269.