core.c 8.8 KB

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