1 /* ATM driver model support. */ 2 3 #include <linux/kernel.h> 4 #include <linux/slab.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 device *cdev, 14 struct device_attribute *attr, char *buf) 15 { 16 struct atm_dev *adev = to_atm_dev(cdev); 17 return sprintf(buf, "%s\n", adev->type); 18 } 19 20 static ssize_t show_address(struct device *cdev, 21 struct device_attribute *attr, char *buf) 22 { 23 char *pos = buf; 24 struct atm_dev *adev = to_atm_dev(cdev); 25 int i; 26 27 for (i = 0; i < (ESI_LEN - 1); i++) 28 pos += sprintf(pos, "%02x:", adev->esi[i]); 29 pos += sprintf(pos, "%02x\n", adev->esi[i]); 30 31 return pos - buf; 32 } 33 34 static ssize_t show_atmaddress(struct device *cdev, 35 struct device_attribute *attr, char *buf) 36 { 37 unsigned long flags; 38 char *pos = buf; 39 struct atm_dev *adev = to_atm_dev(cdev); 40 struct atm_dev_addr *aaddr; 41 int bin[] = { 1, 2, 10, 6, 1 }, *fmt = bin; 42 int i, j; 43 44 spin_lock_irqsave(&adev->lock, flags); 45 list_for_each_entry(aaddr, &adev->local, entry) { 46 for (i = 0, j = 0; i < ATM_ESA_LEN; ++i, ++j) { 47 if (j == *fmt) { 48 pos += sprintf(pos, "."); 49 ++fmt; 50 j = 0; 51 } 52 pos += sprintf(pos, "%02x", 53 aaddr->addr.sas_addr.prv[i]); 54 } 55 pos += sprintf(pos, "\n"); 56 } 57 spin_unlock_irqrestore(&adev->lock, flags); 58 59 return pos - buf; 60 } 61 62 static ssize_t show_carrier(struct device *cdev, 63 struct device_attribute *attr, char *buf) 64 { 65 char *pos = buf; 66 struct atm_dev *adev = to_atm_dev(cdev); 67 68 pos += sprintf(pos, "%d\n", 69 adev->signal == ATM_PHY_SIG_LOST ? 0 : 1); 70 71 return pos - buf; 72 } 73 74 static ssize_t show_link_rate(struct device *cdev, 75 struct device_attribute *attr, char *buf) 76 { 77 char *pos = buf; 78 struct atm_dev *adev = to_atm_dev(cdev); 79 int link_rate; 80 81 /* show the link rate, not the data rate */ 82 switch (adev->link_rate) { 83 case ATM_OC3_PCR: 84 link_rate = 155520000; 85 break; 86 case ATM_OC12_PCR: 87 link_rate = 622080000; 88 break; 89 case ATM_25_PCR: 90 link_rate = 25600000; 91 break; 92 default: 93 link_rate = adev->link_rate * 8 * 53; 94 } 95 pos += sprintf(pos, "%d\n", link_rate); 96 97 return pos - buf; 98 } 99 100 static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); 101 static DEVICE_ATTR(atmaddress, S_IRUGO, show_atmaddress, NULL); 102 static DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL); 103 static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); 104 static DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL); 105 106 static struct device_attribute *atm_attrs[] = { 107 &dev_attr_atmaddress, 108 &dev_attr_address, 109 &dev_attr_carrier, 110 &dev_attr_type, 111 &dev_attr_link_rate, 112 NULL 113 }; 114 115 116 static int atm_uevent(struct device *cdev, struct kobj_uevent_env *env) 117 { 118 struct atm_dev *adev; 119 120 if (!cdev) 121 return -ENODEV; 122 123 adev = to_atm_dev(cdev); 124 if (!adev) 125 return -ENODEV; 126 127 if (add_uevent_var(env, "NAME=%s%d", adev->type, adev->number)) 128 return -ENOMEM; 129 130 return 0; 131 } 132 133 static void atm_release(struct device *cdev) 134 { 135 struct atm_dev *adev = to_atm_dev(cdev); 136 137 kfree(adev); 138 } 139 140 static struct class atm_class = { 141 .name = "atm", 142 .dev_release = atm_release, 143 .dev_uevent = atm_uevent, 144 }; 145 146 int atm_register_sysfs(struct atm_dev *adev) 147 { 148 struct device *cdev = &adev->class_dev; 149 int i, j, err; 150 151 cdev->class = &atm_class; 152 dev_set_drvdata(cdev, adev); 153 154 dev_set_name(cdev, "%s%d", adev->type, adev->number); 155 err = device_register(cdev); 156 if (err < 0) 157 return err; 158 159 for (i = 0; atm_attrs[i]; i++) { 160 err = device_create_file(cdev, atm_attrs[i]); 161 if (err) 162 goto err_out; 163 } 164 165 return 0; 166 167 err_out: 168 for (j = 0; j < i; j++) 169 device_remove_file(cdev, atm_attrs[j]); 170 device_del(cdev); 171 return err; 172 } 173 174 void atm_unregister_sysfs(struct atm_dev *adev) 175 { 176 struct device *cdev = &adev->class_dev; 177 178 device_del(cdev); 179 } 180 181 int __init atm_sysfs_init(void) 182 { 183 return class_register(&atm_class); 184 } 185 186 void __exit atm_sysfs_exit(void) 187 { 188 class_unregister(&atm_class); 189 } 190