char device

 1 /**
 2 * alloc_chrdev_region() - register a range of char device numbers
 3 * @dev: output parameter for first assigned number
 4 * @baseminor: first of the requested range of minor numbers
 5 * @count: the number of minor numbers required
 6 * @name: the name of the associated device or driver
 7 *
 8 * Allocates a range of char device numbers. The major number will be
 9 * chosen dynamically, and returned (along with the first minor number)
10 * in @dev. Returns zero or a negative error code.
11 */
12 int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
13 const char *name)
14 {//分配字符设备的次设备号范围,主设备号有系统动态分配,不需要主动指定
15 struct char_device_struct *cd;
16 cd = __register_chrdev_region(0, baseminor, count, name);
17 if (IS_ERR(cd))
18 return PTR_ERR(cd);
19 *dev = MKDEV(cd->major, cd->baseminor);
20 return 0;
21 }
 1 static struct char_device_struct *
 2 __register_chrdev_region(unsigned int major, unsigned int baseminor,
 3                int minorct, const char *name)
 4 {
 5     struct char_device_struct *cd, **cp;
 6     int ret = 0;
 7     int i;
 8 
 9     cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL);
10     if (cd == NULL)
11         return ERR_PTR(-ENOMEM);
12 
13     mutex_lock(&chrdevs_lock);
14 
15     /* temporary */
16     if (major == 0) {
17         for (i = ARRAY_SIZE(chrdevs)-1; i > 0; i--) {
18             if (chrdevs[i] == NULL)
19                 break;
20         }
21 
22         if (i == 0) {
23             ret = -EBUSY;
24             goto out;
25         }
26         major = i;
27         ret = major;
28     }
29 
30     cd->major = major;
31     cd->baseminor = baseminor;
32     cd->minorct = minorct;
33     strlcpy(cd->name, name, sizeof(cd->name));
34 
35     i = major_to_index(major);
36 
37     for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
38         if ((*cp)->major > major ||
39             ((*cp)->major == major &&
40              (((*cp)->baseminor >= baseminor) ||
41               ((*cp)->baseminor + (*cp)->minorct > baseminor))))
42             break;
43 
44     /* Check for overlapping minor ranges.  */
45     if (*cp && (*cp)->major == major) {
46         int old_min = (*cp)->baseminor;
47         int old_max = (*cp)->baseminor + (*cp)->minorct - 1;
48         int new_min = baseminor;
49         int new_max = baseminor + minorct - 1;
50 
51         /* New driver overlaps from the left.  */
52         if (new_max >= old_min && new_max <= old_max) {
53             ret = -EBUSY;
54             goto out;
55         }
56 
57         /* New driver overlaps from the right.  */
58         if (new_min <= old_max && new_min >= old_min) {
59             ret = -EBUSY;
60             goto out;
61         }
62     }
63 
64     cd->next = *cp;
65     *cp = cd;
66     mutex_unlock(&chrdevs_lock);
67     return cd;
68 out:
69     mutex_unlock(&chrdevs_lock);
70     kfree(cd);
71     return ERR_PTR(ret);
72 }
原文地址:https://www.cnblogs.com/black-mamba/p/7819576.html