Commit | Line | Data |
---|---|---|
656d98b0 RK |
1 | /* ATM driver model support. */ |
2 | ||
3 | #include <linux/config.h> | |
4 | #include <linux/kernel.h> | |
5 | #include <linux/init.h> | |
6 | #include <linux/kobject.h> | |
7 | #include <linux/atmdev.h> | |
8 | #include "common.h" | |
9 | #include "resources.h" | |
10 | ||
11 | #define to_atm_dev(cldev) container_of(cldev, struct atm_dev, class_dev) | |
12 | ||
13 | static ssize_t show_type(struct class_device *cdev, char *buf) | |
14 | { | |
15 | struct atm_dev *adev = to_atm_dev(cdev); | |
16 | return sprintf(buf, "%s\n", adev->type); | |
17 | } | |
18 | ||
19 | static ssize_t show_address(struct class_device *cdev, char *buf) | |
20 | { | |
21 | char *pos = buf; | |
22 | struct atm_dev *adev = to_atm_dev(cdev); | |
23 | int i; | |
24 | ||
25 | for (i = 0; i < (ESI_LEN - 1); i++) | |
26 | pos += sprintf(pos, "%02x:", adev->esi[i]); | |
27 | pos += sprintf(pos, "%02x\n", adev->esi[i]); | |
28 | ||
29 | return pos - buf; | |
30 | } | |
31 | ||
32 | static ssize_t show_atmaddress(struct class_device *cdev, char *buf) | |
33 | { | |
34 | unsigned long flags; | |
35 | char *pos = buf; | |
36 | struct atm_dev *adev = to_atm_dev(cdev); | |
37 | struct atm_dev_addr *aaddr; | |
38 | int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin; | |
39 | int i, j; | |
40 | ||
41 | spin_lock_irqsave(&adev->lock, flags); | |
42 | list_for_each_entry(aaddr, &adev->local, entry) { | |
43 | for(i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) { | |
44 | if (j == *fmt) { | |
45 | pos += sprintf(pos, "."); | |
46 | ++fmt; | |
47 | j = 0; | |
48 | } | |
49 | pos += sprintf(pos, "%02x", aaddr->addr.sas_addr.prv[i]); | |
50 | } | |
51 | pos += sprintf(pos, "\n"); | |
52 | } | |
53 | spin_unlock_irqrestore(&adev->lock, flags); | |
54 | ||
55 | return pos - buf; | |
56 | } | |
57 | ||
58 | static ssize_t show_carrier(struct class_device *cdev, char *buf) | |
59 | { | |
60 | char *pos = buf; | |
61 | struct atm_dev *adev = to_atm_dev(cdev); | |
62 | ||
63 | pos += sprintf(pos, "%d\n", | |
64 | adev->signal == ATM_PHY_SIG_LOST ? 0 : 1); | |
65 | ||
66 | return pos - buf; | |
67 | } | |
68 | ||
69 | static ssize_t show_link_rate(struct class_device *cdev, char *buf) | |
70 | { | |
71 | char *pos = buf; | |
72 | struct atm_dev *adev = to_atm_dev(cdev); | |
73 | int link_rate; | |
74 | ||
75 | /* show the link rate, not the data rate */ | |
76 | switch (adev->link_rate) { | |
77 | case ATM_OC3_PCR: | |
78 | link_rate = 155520000; | |
79 | break; | |
80 | case ATM_OC12_PCR: | |
81 | link_rate = 622080000; | |
82 | break; | |
83 | case ATM_25_PCR: | |
84 | link_rate = 25600000; | |
85 | break; | |
86 | default: | |
87 | link_rate = adev->link_rate * 8 * 53; | |
88 | } | |
89 | pos += sprintf(pos, "%d\n", link_rate); | |
90 | ||
91 | return pos - buf; | |
92 | } | |
93 | ||
94 | static CLASS_DEVICE_ATTR(address, S_IRUGO, show_address, NULL); | |
95 | static CLASS_DEVICE_ATTR(atmaddress, S_IRUGO, show_atmaddress, NULL); | |
96 | static CLASS_DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL); | |
97 | static CLASS_DEVICE_ATTR(type, S_IRUGO, show_type, NULL); | |
98 | static CLASS_DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL); | |
99 | ||
100 | static struct class_device_attribute *atm_attrs[] = { | |
101 | &class_device_attr_atmaddress, | |
102 | &class_device_attr_address, | |
103 | &class_device_attr_carrier, | |
104 | &class_device_attr_type, | |
105 | &class_device_attr_link_rate, | |
106 | NULL | |
107 | }; | |
108 | ||
109 | static int atm_uevent(struct class_device *cdev, char **envp, int num_envp, char *buf, int size) | |
110 | { | |
111 | struct atm_dev *adev; | |
112 | int i = 0, len = 0; | |
113 | ||
114 | if (!cdev) | |
115 | return -ENODEV; | |
116 | ||
117 | adev = to_atm_dev(cdev); | |
118 | if (!adev) | |
119 | return -ENODEV; | |
120 | ||
121 | if (add_uevent_var(envp, num_envp, &i, buf, size, &len, | |
122 | "NAME=%s%d", adev->type, adev->number)) | |
123 | return -ENOMEM; | |
124 | ||
125 | envp[i] = NULL; | |
126 | return 0; | |
127 | } | |
128 | ||
129 | static void atm_release(struct class_device *cdev) | |
130 | { | |
131 | struct atm_dev *adev = to_atm_dev(cdev); | |
132 | ||
133 | kfree(adev); | |
134 | } | |
135 | ||
136 | static struct class atm_class = { | |
137 | .name = "atm", | |
138 | .release = atm_release, | |
139 | .uevent = atm_uevent, | |
140 | }; | |
141 | ||
142 | int atm_register_sysfs(struct atm_dev *adev) | |
143 | { | |
144 | struct class_device *cdev = &adev->class_dev; | |
145 | int i, err; | |
146 | ||
147 | cdev->class = &atm_class; | |
148 | class_set_devdata(cdev, adev); | |
149 | ||
150 | snprintf(cdev->class_id, BUS_ID_SIZE, "%s%d", adev->type, adev->number); | |
151 | err = class_device_register(cdev); | |
152 | if (err < 0) | |
153 | return err; | |
154 | ||
155 | for (i = 0; atm_attrs[i]; i++) | |
156 | class_device_create_file(cdev, atm_attrs[i]); | |
157 | ||
158 | return 0; | |
159 | } | |
160 | ||
161 | void atm_unregister_sysfs(struct atm_dev *adev) | |
162 | { | |
163 | struct class_device *cdev = &adev->class_dev; | |
164 | ||
165 | class_device_del(cdev); | |
166 | } | |
167 | ||
168 | int __init atm_sysfs_init(void) | |
169 | { | |
170 | return class_register(&atm_class); | |
171 | } | |
172 | ||
173 | void __exit atm_sysfs_exit(void) | |
174 | { | |
175 | class_unregister(&atm_class); | |
176 | } |