]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * (C) Copyright IBM Corp. 2004 | |
e018ba1f | 3 | * tape_class.c |
1da177e4 LT |
4 | * |
5 | * Tape class device support | |
6 | * | |
7 | * Author: Stefan Bader <shbader@de.ibm.com> | |
8 | * Based on simple class device code by Greg K-H | |
9 | */ | |
10 | #include "tape_class.h" | |
11 | ||
12 | MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>"); | |
13 | MODULE_DESCRIPTION( | |
14 | "(C) Copyright IBM Corp. 2004 All Rights Reserved.\n" | |
e018ba1f | 15 | "tape_class.c" |
1da177e4 LT |
16 | ); |
17 | MODULE_LICENSE("GPL"); | |
18 | ||
56b22935 | 19 | static struct class *tape_class; |
1da177e4 LT |
20 | |
21 | /* | |
22 | * Register a tape device and return a pointer to the cdev structure. | |
23 | * | |
24 | * device | |
25 | * The pointer to the struct device of the physical (base) device. | |
26 | * drivername | |
27 | * The pointer to the drivers name for it's character devices. | |
28 | * dev | |
29 | * The intended major/minor number. The major number may be 0 to | |
30 | * get a dynamic major number. | |
31 | * fops | |
32 | * The pointer to the drivers file operations for the tape device. | |
33 | * devname | |
34 | * The pointer to the name of the character device. | |
35 | */ | |
36 | struct tape_class_device *register_tape_dev( | |
37 | struct device * device, | |
38 | dev_t dev, | |
9c2e08c5 | 39 | const struct file_operations *fops, |
1da177e4 LT |
40 | char * device_name, |
41 | char * mode_name) | |
42 | { | |
43 | struct tape_class_device * tcd; | |
44 | int rc; | |
45 | char * s; | |
46 | ||
88abaab4 | 47 | tcd = kzalloc(sizeof(struct tape_class_device), GFP_KERNEL); |
1da177e4 LT |
48 | if (!tcd) |
49 | return ERR_PTR(-ENOMEM); | |
50 | ||
1da177e4 LT |
51 | strncpy(tcd->device_name, device_name, TAPECLASS_NAME_LEN); |
52 | for (s = strchr(tcd->device_name, '/'); s; s = strchr(s, '/')) | |
53 | *s = '!'; | |
54 | strncpy(tcd->mode_name, mode_name, TAPECLASS_NAME_LEN); | |
55 | for (s = strchr(tcd->mode_name, '/'); s; s = strchr(s, '/')) | |
56 | *s = '!'; | |
57 | ||
58 | tcd->char_device = cdev_alloc(); | |
59 | if (!tcd->char_device) { | |
60 | rc = -ENOMEM; | |
61 | goto fail_with_tcd; | |
62 | } | |
63 | ||
64 | tcd->char_device->owner = fops->owner; | |
65 | tcd->char_device->ops = fops; | |
66 | tcd->char_device->dev = dev; | |
67 | ||
68 | rc = cdev_add(tcd->char_device, tcd->char_device->dev, 1); | |
69 | if (rc) | |
70 | goto fail_with_cdev; | |
71 | ||
7f021ce1 CH |
72 | tcd->class_device = device_create(tape_class, device, |
73 | tcd->char_device->dev, | |
74 | "%s", tcd->device_name | |
1da177e4 | 75 | ); |
25a2001a | 76 | rc = IS_ERR(tcd->class_device) ? PTR_ERR(tcd->class_device) : 0; |
d7cf0d57 HC |
77 | if (rc) |
78 | goto fail_with_cdev; | |
79 | rc = sysfs_create_link( | |
1da177e4 LT |
80 | &device->kobj, |
81 | &tcd->class_device->kobj, | |
82 | tcd->mode_name | |
83 | ); | |
d7cf0d57 HC |
84 | if (rc) |
85 | goto fail_with_class_device; | |
1da177e4 LT |
86 | |
87 | return tcd; | |
88 | ||
d7cf0d57 | 89 | fail_with_class_device: |
7f021ce1 | 90 | device_destroy(tape_class, tcd->char_device->dev); |
d7cf0d57 | 91 | |
1da177e4 LT |
92 | fail_with_cdev: |
93 | cdev_del(tcd->char_device); | |
94 | ||
95 | fail_with_tcd: | |
96 | kfree(tcd); | |
97 | ||
98 | return ERR_PTR(rc); | |
99 | } | |
100 | EXPORT_SYMBOL(register_tape_dev); | |
101 | ||
102 | void unregister_tape_dev(struct tape_class_device *tcd) | |
103 | { | |
104 | if (tcd != NULL && !IS_ERR(tcd)) { | |
7f021ce1 CH |
105 | sysfs_remove_link(&tcd->class_device->kobj, |
106 | tcd->mode_name); | |
107 | device_destroy(tape_class, tcd->char_device->dev); | |
1da177e4 LT |
108 | cdev_del(tcd->char_device); |
109 | kfree(tcd); | |
110 | } | |
111 | } | |
112 | EXPORT_SYMBOL(unregister_tape_dev); | |
113 | ||
114 | ||
115 | static int __init tape_init(void) | |
116 | { | |
56b22935 | 117 | tape_class = class_create(THIS_MODULE, "tape390"); |
1da177e4 LT |
118 | |
119 | return 0; | |
120 | } | |
121 | ||
122 | static void __exit tape_exit(void) | |
123 | { | |
56b22935 | 124 | class_destroy(tape_class); |
1da177e4 LT |
125 | tape_class = NULL; |
126 | } | |
127 | ||
128 | postcore_initcall(tape_init); | |
129 | module_exit(tape_exit); |