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 }