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