1 /* 2 * Copyright 2008 by Karsten Keil <kkeil@novell.com> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 */ 14 15 #include <linux/types.h> 16 #include <linux/stddef.h> 17 #include <linux/module.h> 18 #include <linux/spinlock.h> 19 #include <linux/mISDNif.h> 20 #include "core.h" 21 22 static u_int debug; 23 24 MODULE_AUTHOR("Karsten Keil"); 25 MODULE_LICENSE("GPL"); 26 module_param(debug, uint, S_IRUGO | S_IWUSR); 27 28 static u64 device_ids; 29 #define MAX_DEVICE_ID 63 30 31 static LIST_HEAD(Bprotocols); 32 static DEFINE_RWLOCK(bp_lock); 33 34 static void mISDN_dev_release(struct device *dev) 35 { 36 /* nothing to do: the device is part of its parent's data structure */ 37 } 38 39 static ssize_t _show_id(struct device *dev, 40 struct device_attribute *attr, char *buf) 41 { 42 struct mISDNdevice *mdev = dev_to_mISDN(dev); 43 44 if (!mdev) 45 return -ENODEV; 46 return sprintf(buf, "%d\n", mdev->id); 47 } 48 49 static ssize_t _show_nrbchan(struct device *dev, 50 struct device_attribute *attr, char *buf) 51 { 52 struct mISDNdevice *mdev = dev_to_mISDN(dev); 53 54 if (!mdev) 55 return -ENODEV; 56 return sprintf(buf, "%d\n", mdev->nrbchan); 57 } 58 59 static ssize_t _show_d_protocols(struct device *dev, 60 struct device_attribute *attr, char *buf) 61 { 62 struct mISDNdevice *mdev = dev_to_mISDN(dev); 63 64 if (!mdev) 65 return -ENODEV; 66 return sprintf(buf, "%d\n", mdev->Dprotocols); 67 } 68 69 static ssize_t _show_b_protocols(struct device *dev, 70 struct device_attribute *attr, char *buf) 71 { 72 struct mISDNdevice *mdev = dev_to_mISDN(dev); 73 74 if (!mdev) 75 return -ENODEV; 76 return sprintf(buf, "%d\n", mdev->Bprotocols | get_all_Bprotocols()); 77 } 78 79 static ssize_t _show_protocol(struct device *dev, 80 struct device_attribute *attr, char *buf) 81 { 82 struct mISDNdevice *mdev = dev_to_mISDN(dev); 83 84 if (!mdev) 85 return -ENODEV; 86 return sprintf(buf, "%d\n", mdev->D.protocol); 87 } 88 89 static ssize_t _show_name(struct device *dev, 90 struct device_attribute *attr, char *buf) 91 { 92 strcpy(buf, dev_name(dev)); 93 return strlen(buf); 94 } 95 96 #if 0 /* hangs */ 97 static ssize_t _set_name(struct device *dev, struct device_attribute *attr, 98 const char *buf, size_t count) 99 { 100 int err = 0; 101 char *out = kmalloc(count + 1, GFP_KERNEL); 102 103 if (!out) 104 return -ENOMEM; 105 106 memcpy(out, buf, count); 107 if (count && out[count - 1] == '\n') 108 out[--count] = 0; 109 if (count) 110 err = device_rename(dev, out); 111 kfree(out); 112 113 return (err < 0) ? err : count; 114 } 115 #endif 116 117 static ssize_t _show_channelmap(struct device *dev, 118 struct device_attribute *attr, char *buf) 119 { 120 struct mISDNdevice *mdev = dev_to_mISDN(dev); 121 char *bp = buf; 122 int i; 123 124 for (i = 0; i <= mdev->nrbchan; i++) 125 *bp++ = test_channelmap(i, mdev->channelmap) ? '1' : '0'; 126 127 return bp - buf; 128 } 129 130 static struct device_attribute mISDN_dev_attrs[] = { 131 __ATTR(id, S_IRUGO, _show_id, NULL), 132 __ATTR(d_protocols, S_IRUGO, _show_d_protocols, NULL), 133 __ATTR(b_protocols, S_IRUGO, _show_b_protocols, NULL), 134 __ATTR(protocol, S_IRUGO, _show_protocol, NULL), 135 __ATTR(channelmap, S_IRUGO, _show_channelmap, NULL), 136 __ATTR(nrbchan, S_IRUGO, _show_nrbchan, NULL), 137 __ATTR(name, S_IRUGO, _show_name, NULL), 138 /* __ATTR(name, S_IRUGO|S_IWUSR, _show_name, _set_name), */ 139 {} 140 }; 141 142 #ifdef CONFIG_HOTPLUG 143 static int mISDN_uevent(struct device *dev, struct kobj_uevent_env *env) 144 { 145 struct mISDNdevice *mdev = dev_to_mISDN(dev); 146 147 if (!mdev) 148 return 0; 149 150 if (add_uevent_var(env, "nchans=%d", mdev->nrbchan)) 151 return -ENOMEM; 152 153 return 0; 154 } 155 #endif 156 157 static void mISDN_class_release(struct class *cls) 158 { 159 /* do nothing, it's static */ 160 } 161 162 static struct class mISDN_class = { 163 .name = "mISDN", 164 .owner = THIS_MODULE, 165 #ifdef CONFIG_HOTPLUG 166 .dev_uevent = mISDN_uevent, 167 #endif 168 .dev_attrs = mISDN_dev_attrs, 169 .dev_release = mISDN_dev_release, 170 .class_release = mISDN_class_release, 171 }; 172 173 static int 174 _get_mdevice(struct device *dev, void *id) 175 { 176 struct mISDNdevice *mdev = dev_to_mISDN(dev); 177 178 if (!mdev) 179 return 0; 180 if (mdev->id != *(u_int *)id) 181 return 0; 182 return 1; 183 } 184 185 struct mISDNdevice 186 *get_mdevice(u_int id) 187 { 188 return dev_to_mISDN(class_find_device(&mISDN_class, NULL, &id, 189 _get_mdevice)); 190 } 191 192 static int 193 _get_mdevice_count(struct device *dev, void *cnt) 194 { 195 *(int *)cnt += 1; 196 return 0; 197 } 198 199 int 200 get_mdevice_count(void) 201 { 202 int cnt = 0; 203 204 class_for_each_device(&mISDN_class, NULL, &cnt, _get_mdevice_count); 205 return cnt; 206 } 207 208 static int 209 get_free_devid(void) 210 { 211 u_int i; 212 213 for (i = 0; i <= MAX_DEVICE_ID; i++) 214 if (!test_and_set_bit(i, (u_long *)&device_ids)) 215 break; 216 if (i > MAX_DEVICE_ID) 217 return -EBUSY; 218 return i; 219 } 220 221 int 222 mISDN_register_device(struct mISDNdevice *dev, 223 struct device *parent, char *name) 224 { 225 int err; 226 227 err = get_free_devid(); 228 if (err < 0) 229 goto error1; 230 dev->id = err; 231 232 device_initialize(&dev->dev); 233 if (name && name[0]) 234 dev_set_name(&dev->dev, "%s", name); 235 else 236 dev_set_name(&dev->dev, "mISDN%d", dev->id); 237 if (debug & DEBUG_CORE) 238 printk(KERN_DEBUG "mISDN_register %s %d\n", 239 dev_name(&dev->dev), dev->id); 240 err = create_stack(dev); 241 if (err) 242 goto error1; 243 244 dev->dev.class = &mISDN_class; 245 dev->dev.platform_data = dev; 246 dev->dev.parent = parent; 247 dev_set_drvdata(&dev->dev, dev); 248 249 err = device_add(&dev->dev); 250 if (err) 251 goto error3; 252 return 0; 253 254 error3: 255 delete_stack(dev); 256 return err; 257 error1: 258 return err; 259 260 } 261 EXPORT_SYMBOL(mISDN_register_device); 262 263 void 264 mISDN_unregister_device(struct mISDNdevice *dev) { 265 if (debug & DEBUG_CORE) 266 printk(KERN_DEBUG "mISDN_unregister %s %d\n", 267 dev_name(&dev->dev), dev->id); 268 /* sysfs_remove_link(&dev->dev.kobj, "device"); */ 269 device_del(&dev->dev); 270 dev_set_drvdata(&dev->dev, NULL); 271 272 test_and_clear_bit(dev->id, (u_long *)&device_ids); 273 delete_stack(dev); 274 put_device(&dev->dev); 275 } 276 EXPORT_SYMBOL(mISDN_unregister_device); 277 278 u_int 279 get_all_Bprotocols(void) 280 { 281 struct Bprotocol *bp; 282 u_int m = 0; 283 284 read_lock(&bp_lock); 285 list_for_each_entry(bp, &Bprotocols, list) 286 m |= bp->Bprotocols; 287 read_unlock(&bp_lock); 288 return m; 289 } 290 291 struct Bprotocol * 292 get_Bprotocol4mask(u_int m) 293 { 294 struct Bprotocol *bp; 295 296 read_lock(&bp_lock); 297 list_for_each_entry(bp, &Bprotocols, list) 298 if (bp->Bprotocols & m) { 299 read_unlock(&bp_lock); 300 return bp; 301 } 302 read_unlock(&bp_lock); 303 return NULL; 304 } 305 306 struct Bprotocol * 307 get_Bprotocol4id(u_int id) 308 { 309 u_int m; 310 311 if (id < ISDN_P_B_START || id > 63) { 312 printk(KERN_WARNING "%s id not in range %d\n", 313 __func__, id); 314 return NULL; 315 } 316 m = 1 << (id & ISDN_P_B_MASK); 317 return get_Bprotocol4mask(m); 318 } 319 320 int 321 mISDN_register_Bprotocol(struct Bprotocol *bp) 322 { 323 u_long flags; 324 struct Bprotocol *old; 325 326 if (debug & DEBUG_CORE) 327 printk(KERN_DEBUG "%s: %s/%x\n", __func__, 328 bp->name, bp->Bprotocols); 329 old = get_Bprotocol4mask(bp->Bprotocols); 330 if (old) { 331 printk(KERN_WARNING 332 "register duplicate protocol old %s/%x new %s/%x\n", 333 old->name, old->Bprotocols, bp->name, bp->Bprotocols); 334 return -EBUSY; 335 } 336 write_lock_irqsave(&bp_lock, flags); 337 list_add_tail(&bp->list, &Bprotocols); 338 write_unlock_irqrestore(&bp_lock, flags); 339 return 0; 340 } 341 EXPORT_SYMBOL(mISDN_register_Bprotocol); 342 343 void 344 mISDN_unregister_Bprotocol(struct Bprotocol *bp) 345 { 346 u_long flags; 347 348 if (debug & DEBUG_CORE) 349 printk(KERN_DEBUG "%s: %s/%x\n", __func__, bp->name, 350 bp->Bprotocols); 351 write_lock_irqsave(&bp_lock, flags); 352 list_del(&bp->list); 353 write_unlock_irqrestore(&bp_lock, flags); 354 } 355 EXPORT_SYMBOL(mISDN_unregister_Bprotocol); 356 357 static int 358 mISDNInit(void) 359 { 360 int err; 361 362 printk(KERN_INFO "Modular ISDN core version %d.%d.%d\n", 363 MISDN_MAJOR_VERSION, MISDN_MINOR_VERSION, MISDN_RELEASE); 364 mISDN_init_clock(&debug); 365 mISDN_initstack(&debug); 366 err = class_register(&mISDN_class); 367 if (err) 368 goto error1; 369 err = mISDN_inittimer(&debug); 370 if (err) 371 goto error2; 372 err = l1_init(&debug); 373 if (err) 374 goto error3; 375 err = Isdnl2_Init(&debug); 376 if (err) 377 goto error4; 378 err = misdn_sock_init(&debug); 379 if (err) 380 goto error5; 381 return 0; 382 383 error5: 384 Isdnl2_cleanup(); 385 error4: 386 l1_cleanup(); 387 error3: 388 mISDN_timer_cleanup(); 389 error2: 390 class_unregister(&mISDN_class); 391 error1: 392 return err; 393 } 394 395 static void mISDN_cleanup(void) 396 { 397 misdn_sock_cleanup(); 398 Isdnl2_cleanup(); 399 l1_cleanup(); 400 mISDN_timer_cleanup(); 401 class_unregister(&mISDN_class); 402 403 printk(KERN_DEBUG "mISDNcore unloaded\n"); 404 } 405 406 module_init(mISDNInit); 407 module_exit(mISDN_cleanup); 408 409