xpp_dahdi.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227
  1. /*
  2. * Written by Oron Peled <oron@actcom.co.il>
  3. * Copyright (C) 2004, Xorcom
  4. *
  5. * Derived from ztdummy
  6. *
  7. * Copyright (C) 2002, Hermes Softlab
  8. * Copyright (C) 2004, Digium, Inc.
  9. *
  10. * All rights reserved.
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  25. *
  26. */
  27. #include <linux/version.h>
  28. #include <linux/kernel.h>
  29. #include <linux/sched.h>
  30. #include <linux/errno.h>
  31. #include <linux/module.h>
  32. #include <linux/device.h>
  33. #include <linux/init.h>
  34. #include <linux/delay.h> /* for udelay */
  35. #include <linux/interrupt.h>
  36. #include <linux/proc_fs.h>
  37. #include <linux/seq_file.h>
  38. #include <dahdi/kernel.h>
  39. #include "xbus-core.h"
  40. #include "xproto.h"
  41. #include "xpp_dahdi.h"
  42. #include "parport_debug.h"
  43. static const char rcsid[] = "$Id$";
  44. #ifdef CONFIG_PROC_FS
  45. struct proc_dir_entry *xpp_proc_toplevel = NULL;
  46. #define PROC_DIR "xpp"
  47. #define PROC_XPD_SUMMARY "summary"
  48. #endif
  49. #define MAX_QUEUE_LEN 10000
  50. #define DELAY_UNTIL_DIALTONE 3000
  51. DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
  52. EXPORT_SYMBOL(debug);
  53. static DEF_PARM_BOOL(prefmaster, 0, 0644,
  54. "Do we want to be dahdi preferred sync master");
  55. // DEF_ARRAY(int, pcmtx, 4, 0, "Forced PCM values to transmit");
  56. #include "dahdi_debug.h"
  57. static void phonedev_cleanup(xpd_t *xpd);
  58. #ifdef DEBUG_SYNC_PARPORT
  59. /*
  60. * Use parallel port to sample our PCM sync and diagnose quality and
  61. * potential problems. A logic analizer or a scope should be connected
  62. * to the data bits of the parallel port.
  63. *
  64. * Array parameter: Choose the two xbuses Id's to sample.
  65. * This can be changed on runtime as well. Example:
  66. * echo "3,5" > /sys/module/xpp/parameters/parport_xbuses
  67. */
  68. static int parport_xbuses[2] = { 0, 1 };
  69. unsigned int parport_xbuses_num_values;
  70. module_param_array(parport_xbuses, int, &parport_xbuses_num_values, 0577);
  71. MODULE_PARM_DESC(parport_xbuses, "Id's of xbuses to sample (1-2)");
  72. /*
  73. * Flip a single bit in the parallel port:
  74. * - The bit number is either bitnum0 or bitnum1
  75. * - Bit is selected by xbus number from parport_xbuses[]
  76. */
  77. void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1)
  78. {
  79. int num = xbus->num;
  80. if (num == parport_xbuses[0])
  81. flip_parport_bit(bitnum0);
  82. if (num == parport_xbuses[1])
  83. flip_parport_bit(bitnum1);
  84. }
  85. EXPORT_SYMBOL(xbus_flip_bit);
  86. #endif
  87. static atomic_t num_registered_spans = ATOMIC_INIT(0);
  88. int total_registered_spans(void)
  89. {
  90. return atomic_read(&num_registered_spans);
  91. }
  92. #ifdef CONFIG_PROC_FS
  93. static const struct file_operations xpd_read_proc_ops;
  94. #endif
  95. /*------------------------- XPD Management -------------------------*/
  96. /*
  97. * Called by put_xpd() when XPD has no more references.
  98. */
  99. static void xpd_destroy(struct kref *kref)
  100. {
  101. xpd_t *xpd;
  102. xpd = kref_to_xpd(kref);
  103. XPD_DBG(DEVICES, xpd, "%s\n", __func__);
  104. xpd_device_unregister(xpd);
  105. }
  106. int refcount_xpd(xpd_t *xpd)
  107. {
  108. struct kref *kref = &xpd->kref;
  109. return atomic_read(&kref->refcount);
  110. }
  111. xpd_t *get_xpd(const char *msg, xpd_t *xpd)
  112. {
  113. XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n", msg, refcount_xpd(xpd));
  114. kref_get(&xpd->kref);
  115. return xpd;
  116. }
  117. EXPORT_SYMBOL(get_xpd);
  118. void put_xpd(const char *msg, xpd_t *xpd)
  119. {
  120. XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n", msg, refcount_xpd(xpd));
  121. kref_put(&xpd->kref, xpd_destroy);
  122. }
  123. EXPORT_SYMBOL(put_xpd);
  124. static void xpd_proc_remove(xbus_t *xbus, xpd_t *xpd)
  125. {
  126. #ifdef CONFIG_PROC_FS
  127. if (xpd->proc_xpd_dir) {
  128. if (xpd->proc_xpd_summary) {
  129. XPD_DBG(PROC, xpd, "Removing proc '%s'\n",
  130. PROC_XPD_SUMMARY);
  131. remove_proc_entry(PROC_XPD_SUMMARY, xpd->proc_xpd_dir);
  132. xpd->proc_xpd_summary = NULL;
  133. }
  134. XPD_DBG(PROC, xpd, "Removing %s/%s proc directory\n",
  135. xbus->busname, xpd->xpdname);
  136. remove_proc_entry(xpd->xpdname, xbus->proc_xbus_dir);
  137. xpd->proc_xpd_dir = NULL;
  138. }
  139. #endif
  140. }
  141. static int xpd_proc_create(xbus_t *xbus, xpd_t *xpd)
  142. {
  143. #ifdef CONFIG_PROC_FS
  144. XPD_DBG(PROC, xpd, "Creating proc directory\n");
  145. xpd->proc_xpd_dir = proc_mkdir(xpd->xpdname, xbus->proc_xbus_dir);
  146. if (!xpd->proc_xpd_dir) {
  147. XPD_ERR(xpd, "Failed to create proc directory\n");
  148. goto err;
  149. }
  150. xpd->proc_xpd_summary = proc_create_data(PROC_XPD_SUMMARY, 0444,
  151. xpd->proc_xpd_dir,
  152. &xpd_read_proc_ops, xpd);
  153. if (!xpd->proc_xpd_summary) {
  154. XPD_ERR(xpd, "Failed to create proc file '%s'\n",
  155. PROC_XPD_SUMMARY);
  156. goto err;
  157. }
  158. SET_PROC_DIRENTRY_OWNER(xpd->proc_xpd_summary);
  159. #endif
  160. return 0;
  161. #ifdef CONFIG_PROC_FS
  162. err:
  163. xpd_proc_remove(xbus, xpd);
  164. return -EFAULT;
  165. #endif
  166. }
  167. void xpd_free(xpd_t *xpd)
  168. {
  169. xbus_t *xbus = NULL;
  170. if (!xpd)
  171. return;
  172. if (xpd->xproto)
  173. xproto_put(xpd->xproto); /* was taken in xpd_alloc() */
  174. xpd->xproto = NULL;
  175. xbus = xpd->xbus;
  176. if (!xbus)
  177. return;
  178. XPD_DBG(DEVICES, xpd, "\n");
  179. xpd_proc_remove(xbus, xpd);
  180. xbus_xpd_unbind(xbus, xpd);
  181. phonedev_cleanup(xpd);
  182. KZFREE(xpd);
  183. DBG(DEVICES, "refcount_xbus=%d\n", refcount_xbus(xbus));
  184. /*
  185. * This must be last, so the xbus cannot be released before the xpd
  186. */
  187. put_xbus(__func__, xbus); /* was taken in xpd_alloc() */
  188. }
  189. EXPORT_SYMBOL(xpd_free);
  190. /*
  191. * Synchronous part of XPD detection.
  192. * Called from new_card()
  193. */
  194. int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit,
  195. int subunit, __u8 type, __u8 subtype, int subunits,
  196. int subunit_ports, __u8 port_dir)
  197. {
  198. xpd_t *xpd = NULL;
  199. bool to_phone;
  200. BUG_ON(type == XPD_TYPE_NOMODULE);
  201. to_phone = BIT(subunit) & port_dir;
  202. BUG_ON(!xbus);
  203. xpd = xpd_byaddr(xbus, unit, subunit);
  204. if (xpd) {
  205. XPD_NOTICE(xpd, "XPD at %d%d already exists\n", unit, subunit);
  206. return 0;
  207. }
  208. if (subunit_ports <= 0 || subunit_ports > CHANNELS_PERXPD) {
  209. XBUS_NOTICE(xbus, "Illegal number of ports %d for XPD %d%d\n",
  210. subunit_ports, unit, subunit);
  211. return 0;
  212. }
  213. xpd =
  214. proto_table->xops->card_new(xbus, unit, subunit, proto_table,
  215. subtype, subunits, subunit_ports,
  216. to_phone);
  217. if (!xpd) {
  218. XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d,%d) failed. Ignored.\n",
  219. unit, subunit, proto_table->type, subtype,
  220. to_phone);
  221. return -EINVAL;
  222. }
  223. return 0;
  224. }
  225. EXPORT_SYMBOL(create_xpd);
  226. #ifdef CONFIG_PROC_FS
  227. /**
  228. * Prints a general procfs entry for the bus, under xpp/BUSNAME/summary
  229. */
  230. static int xpd_read_proc_show(struct seq_file *sfile, void *data)
  231. {
  232. int len = 0;
  233. xpd_t *xpd = sfile->private;
  234. int i;
  235. if (!xpd)
  236. return -EINVAL;
  237. seq_printf(sfile,
  238. "%s (%s, card %s, span %d)\n" "timing_priority: %d\n"
  239. "timer_count: %d span->mainttimer=%d\n", xpd->xpdname,
  240. xpd->type_name, (xpd->card_present) ? "present" : "missing",
  241. (SPAN_REGISTERED(xpd)) ? PHONEDEV(xpd).span.spanno : 0,
  242. PHONEDEV(xpd).timing_priority, xpd->timer_count,
  243. PHONEDEV(xpd).span.mainttimer);
  244. seq_printf(sfile, "xpd_state: %s (%d)\n",
  245. xpd_statename(xpd->xpd_state), xpd->xpd_state);
  246. seq_printf(sfile, "open_counter=%d refcount=%d\n",
  247. atomic_read(&PHONEDEV(xpd).open_counter),
  248. refcount_xpd(xpd));
  249. seq_printf(sfile, "Address: U=%d S=%d\n", xpd->addr.unit,
  250. xpd->addr.subunit);
  251. seq_printf(sfile, "Subunits: %d\n", xpd->subunits);
  252. seq_printf(sfile, "Type: %d.%d\n\n", xpd->type, xpd->subtype);
  253. seq_printf(sfile, "pcm_len=%d\n\n", PHONEDEV(xpd).pcm_len);
  254. seq_printf(sfile, "wanted_pcm_mask=0x%04X\n\n",
  255. PHONEDEV(xpd).wanted_pcm_mask);
  256. seq_printf(sfile, "mute_dtmf=0x%04X\n\n",
  257. PHONEDEV(xpd).mute_dtmf);
  258. seq_printf(sfile, "STATES:");
  259. seq_printf(sfile, "\n\t%-17s: ", "output_relays");
  260. for_each_line(xpd, i) {
  261. seq_printf(sfile, "%d ",
  262. IS_SET(PHONEDEV(xpd).digital_outputs, i));
  263. }
  264. seq_printf(sfile, "\n\t%-17s: ", "input_relays");
  265. for_each_line(xpd, i) {
  266. seq_printf(sfile, "%d ",
  267. IS_SET(PHONEDEV(xpd).digital_inputs, i));
  268. }
  269. seq_printf(sfile, "\n\t%-17s: ", "offhook");
  270. for_each_line(xpd, i) {
  271. seq_printf(sfile, "%d ", IS_OFFHOOK(xpd, i));
  272. }
  273. seq_printf(sfile, "\n\t%-17s: ", "oht_pcm_pass");
  274. for_each_line(xpd, i) {
  275. seq_printf(sfile, "%d ",
  276. IS_SET(PHONEDEV(xpd).oht_pcm_pass, i));
  277. }
  278. seq_printf(sfile, "\n\t%-17s: ", "msg_waiting");
  279. for_each_line(xpd, i) {
  280. seq_printf(sfile, "%d ", PHONEDEV(xpd).msg_waiting[i]);
  281. }
  282. seq_printf(sfile, "\n\t%-17s: ", "ringing");
  283. for_each_line(xpd, i) {
  284. seq_printf(sfile, "%d ", PHONEDEV(xpd).ringing[i]);
  285. }
  286. seq_printf(sfile, "\n\t%-17s: ", "no_pcm");
  287. for_each_line(xpd, i) {
  288. seq_printf(sfile, "%d ", IS_SET(PHONEDEV(xpd).no_pcm, i));
  289. }
  290. #if 1
  291. if (SPAN_REGISTERED(xpd)) {
  292. seq_printf(sfile,
  293. "\nPCM:\n |"
  294. " [readchunk] |"
  295. " [writechunk] | W D");
  296. for_each_line(xpd, i) {
  297. struct dahdi_chan *chan = XPD_CHAN(xpd, i);
  298. __u8 rchunk[DAHDI_CHUNKSIZE];
  299. __u8 wchunk[DAHDI_CHUNKSIZE];
  300. __u8 *rp;
  301. __u8 *wp;
  302. int j;
  303. if (IS_SET(PHONEDEV(xpd).digital_outputs, i))
  304. continue;
  305. if (IS_SET(PHONEDEV(xpd).digital_inputs, i))
  306. continue;
  307. if (IS_SET(PHONEDEV(xpd).digital_signalling, i))
  308. continue;
  309. rp = chan->readchunk;
  310. wp = chan->writechunk;
  311. memcpy(rchunk, rp, DAHDI_CHUNKSIZE);
  312. memcpy(wchunk, wp, DAHDI_CHUNKSIZE);
  313. seq_printf(sfile, "\n port %2d> | ", i);
  314. for (j = 0; j < DAHDI_CHUNKSIZE; j++)
  315. seq_printf(sfile, "%02X ", rchunk[j]);
  316. seq_printf(sfile, " | ");
  317. for (j = 0; j < DAHDI_CHUNKSIZE; j++)
  318. seq_printf(sfile, "%02X ", wchunk[j]);
  319. seq_printf(sfile, " | %c",
  320. (IS_SET(PHONEDEV(xpd).wanted_pcm_mask, i))
  321. ? '+' : ' ');
  322. seq_printf(sfile, " %c",
  323. (IS_SET(PHONEDEV(xpd).mute_dtmf, i))
  324. ? '-' : ' ');
  325. }
  326. }
  327. #endif
  328. #if 0
  329. if (SPAN_REGISTERED(xpd)) {
  330. seq_printf(sfile, "\nSignalling:\n");
  331. for_each_line(xpd, i) {
  332. struct dahdi_chan *chan = XPD_CHAN(xpd, i);
  333. seq_printf(sfile,
  334. "\t%2d> sigcap=0x%04X sig=0x%04X\n", i,
  335. chan->sigcap, chan->sig);
  336. }
  337. }
  338. #endif
  339. seq_printf(sfile, "\nCOUNTERS:\n");
  340. for (i = 0; i < XPD_COUNTER_MAX; i++) {
  341. seq_printf(sfile, "\t\t%-20s = %d\n",
  342. xpd_counters[i].name, xpd->counters[i]);
  343. }
  344. seq_printf(sfile, "<-- len=%d\n", len);
  345. return 0;
  346. }
  347. static int xpd_read_proc_open(struct inode *inode, struct file *file)
  348. {
  349. return single_open(file, xpd_read_proc_show, PDE_DATA(inode));
  350. }
  351. static const struct file_operations xpd_read_proc_ops = {
  352. .owner = THIS_MODULE,
  353. .open = xpd_read_proc_open,
  354. .read = seq_read,
  355. .llseek = seq_lseek,
  356. .release = single_release,
  357. };
  358. #endif
  359. const char *xpd_statename(enum xpd_state st)
  360. {
  361. switch (st) {
  362. case XPD_STATE_START:
  363. return "START";
  364. case XPD_STATE_INIT_REGS:
  365. return "INIT_REGS";
  366. case XPD_STATE_READY:
  367. return "READY";
  368. case XPD_STATE_NOHW:
  369. return "NOHW";
  370. }
  371. return NULL;
  372. }
  373. bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate)
  374. {
  375. BUG_ON(!xpd);
  376. XPD_DBG(DEVICES, xpd, "%s: %s (%d) -> %s (%d)\n", __func__,
  377. xpd_statename(xpd->xpd_state), xpd->xpd_state,
  378. xpd_statename(newstate), newstate);
  379. switch (newstate) {
  380. case XPD_STATE_START:
  381. goto badstate;
  382. case XPD_STATE_INIT_REGS:
  383. if (xpd->xpd_state != XPD_STATE_START)
  384. goto badstate;
  385. if (xpd->addr.subunit != 0) {
  386. XPD_NOTICE(xpd,
  387. "%s: Moving to %s allowed only for subunit 0\n",
  388. __func__, xpd_statename(newstate));
  389. goto badstate;
  390. }
  391. break;
  392. case XPD_STATE_READY:
  393. if (xpd->addr.subunit == 0) {
  394. /* Unit 0 script initialize registers of all subunits */
  395. if (xpd->xpd_state != XPD_STATE_INIT_REGS)
  396. goto badstate;
  397. } else {
  398. if (xpd->xpd_state != XPD_STATE_START)
  399. goto badstate;
  400. }
  401. break;
  402. case XPD_STATE_NOHW:
  403. break;
  404. default:
  405. XPD_ERR(xpd, "%s: Unknown newstate=%d\n", __func__, newstate);
  406. }
  407. xpd->xpd_state = newstate;
  408. return 1;
  409. badstate:
  410. XPD_NOTICE(xpd, "%s: cannot transition: %s (%d) -> %s (%d)\n", __func__,
  411. xpd_statename(xpd->xpd_state), xpd->xpd_state,
  412. xpd_statename(newstate), newstate);
  413. return 0;
  414. }
  415. /*
  416. * Cleanup/initialize phonedev
  417. */
  418. static void phonedev_cleanup(xpd_t *xpd)
  419. {
  420. struct phonedev *phonedev = &PHONEDEV(xpd);
  421. unsigned int x;
  422. for (x = 0; x < phonedev->channels; x++) {
  423. if (phonedev->chans[x]) {
  424. KZFREE(phonedev->chans[x]);
  425. phonedev->chans[x] = NULL;
  426. }
  427. if (phonedev->ec[x]) {
  428. KZFREE(phonedev->ec[x]);
  429. phonedev->ec[x] = NULL;
  430. }
  431. }
  432. phonedev->channels = 0;
  433. }
  434. int phonedev_alloc_channels(xpd_t *xpd, int channels)
  435. {
  436. struct phonedev *phonedev = &PHONEDEV(xpd);
  437. int old_channels = phonedev->channels;
  438. unsigned int x;
  439. XPD_DBG(DEVICES, xpd, "Reallocating channels: %d -> %d\n",
  440. old_channels, channels);
  441. phonedev_cleanup(xpd);
  442. phonedev->channels = channels;
  443. for (x = 0; x < phonedev->channels; x++) {
  444. if (!
  445. (phonedev->chans[x] =
  446. KZALLOC(sizeof(*(phonedev->chans[x])), GFP_KERNEL))) {
  447. ERR("%s: Unable to allocate channel %d\n", __func__, x);
  448. goto err;
  449. }
  450. phonedev->ec[x] =
  451. KZALLOC(sizeof(*(phonedev->ec[x])), GFP_KERNEL);
  452. if (!phonedev->ec[x]) {
  453. ERR("%s: Unable to allocate ec state %d\n", __func__,
  454. x);
  455. goto err;
  456. }
  457. }
  458. return 0;
  459. err:
  460. phonedev_cleanup(xpd);
  461. return -ENOMEM;
  462. }
  463. EXPORT_SYMBOL(phonedev_alloc_channels);
  464. __must_check static int phonedev_init(xpd_t *xpd,
  465. const xproto_table_t *proto_table,
  466. int channels, xpp_line_t no_pcm)
  467. {
  468. struct phonedev *phonedev = &PHONEDEV(xpd);
  469. spin_lock_init(&phonedev->lock_recompute_pcm);
  470. phonedev->no_pcm = no_pcm;
  471. phonedev->offhook_state = 0x0; /* ONHOOK */
  472. phonedev->phoneops = proto_table->phoneops;
  473. phonedev->digital_outputs = 0;
  474. phonedev->digital_inputs = 0;
  475. atomic_set(&phonedev->dahdi_registered, 0);
  476. atomic_set(&phonedev->open_counter, 0);
  477. if (phonedev_alloc_channels(xpd, channels) < 0)
  478. goto err;
  479. return 0;
  480. err:
  481. return -ENOMEM;
  482. }
  483. /*
  484. * xpd_alloc - Allocator for new XPD's
  485. *
  486. */
  487. __must_check xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit,
  488. int subtype, int subunits, size_t privsize,
  489. const xproto_table_t *proto_table, int channels)
  490. {
  491. xpd_t *xpd = NULL;
  492. size_t alloc_size = sizeof(xpd_t) + privsize;
  493. int type = proto_table->type;
  494. xpp_line_t no_pcm = 0;
  495. BUG_ON(!proto_table);
  496. XBUS_DBG(DEVICES, xbus, "type=%d channels=%d (alloc_size=%zd)\n", type,
  497. channels, alloc_size);
  498. if (channels > CHANNELS_PERXPD) {
  499. XBUS_ERR(xbus, "%s: type=%d: too many channels %d\n", __func__,
  500. type, channels);
  501. goto err;
  502. }
  503. if ((xpd = KZALLOC(alloc_size, GFP_KERNEL)) == NULL) {
  504. XBUS_ERR(xbus, "%s: type=%d: Unable to allocate memory\n",
  505. __func__, type);
  506. goto err;
  507. }
  508. xpd->priv = (__u8 *)xpd + sizeof(xpd_t);
  509. spin_lock_init(&xpd->lock);
  510. xpd->card_present = 0;
  511. xpd->type = proto_table->type;
  512. xpd->xproto = proto_table;
  513. xpd->xops = proto_table->xops;
  514. xpd->xpd_state = XPD_STATE_START;
  515. xpd->subtype = subtype;
  516. xpd->subunits = subunits;
  517. kref_init(&xpd->kref);
  518. /* For USB-1 disable some channels */
  519. if (MAX_SEND_SIZE(xbus) < RPACKET_SIZE(GLOBAL, PCM_WRITE)) {
  520. no_pcm =
  521. 0x7F | PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).
  522. digital_inputs;
  523. XBUS_NOTICE(xbus,
  524. "max xframe size = %d, disabling some PCM channels. "
  525. "no_pcm=0x%04X\n",
  526. MAX_SEND_SIZE(xbus), PHONEDEV(xpd).no_pcm);
  527. }
  528. if (phonedev_init(xpd, proto_table, channels, no_pcm) < 0)
  529. goto err;
  530. xbus_xpd_bind(xbus, xpd, unit, subunit);
  531. if (xpd_proc_create(xbus, xpd) < 0)
  532. goto err;
  533. /*
  534. * This makes sure the xbus cannot be removed before this xpd
  535. * is removed in xpd_free()
  536. */
  537. xbus = get_xbus(__func__, xbus->num); /* returned in xpd_free() */
  538. xproto_get(type); /* will be returned in xpd_free() */
  539. return xpd;
  540. err:
  541. if (xpd) {
  542. xpd_proc_remove(xbus, xpd);
  543. phonedev_cleanup(xpd);
  544. KZFREE(xpd);
  545. }
  546. return NULL;
  547. }
  548. EXPORT_SYMBOL(xpd_alloc);
  549. /*
  550. * The xpd isn't open by anyone, we can unregister it and free it
  551. */
  552. void xpd_remove(xpd_t *xpd)
  553. {
  554. BUG_ON(!xpd);
  555. XPD_INFO(xpd, "Remove\n");
  556. CALL_XMETHOD(card_remove, xpd);
  557. xpd_free(xpd);
  558. }
  559. void update_xpd_status(xpd_t *xpd, int alarm_flag)
  560. {
  561. struct dahdi_span *span = &PHONEDEV(xpd).span;
  562. if (!SPAN_REGISTERED(xpd)) {
  563. #if 0
  564. XPD_NOTICE(xpd,
  565. "%s: XPD is not registered. Skipping.\n",
  566. __func__);
  567. #endif
  568. return;
  569. }
  570. switch (alarm_flag) {
  571. case DAHDI_ALARM_NONE:
  572. xpd->last_response = jiffies;
  573. break;
  574. default:
  575. // Nothing
  576. break;
  577. }
  578. if (span->alarms == alarm_flag)
  579. return;
  580. XPD_DBG(GENERAL, xpd, "Update XPD alarms: %s -> %02X\n",
  581. PHONEDEV(xpd).span.name, alarm_flag);
  582. span->alarms = alarm_flag;
  583. dahdi_alarm_notify(span);
  584. }
  585. EXPORT_SYMBOL(update_xpd_status);
  586. /*
  587. * Used to block/pass PCM during onhook-transfers. E.g:
  588. * - Playing FSK after FXS ONHOOK for MWI (non-neon style)
  589. * - Playing DTFM/FSK for FXO Caller-ID detection.
  590. */
  591. void oht_pcm(xpd_t *xpd, int pos, bool pass)
  592. {
  593. if (pass) {
  594. LINE_DBG(SIGNAL, xpd, pos, "OHT PCM: pass\n");
  595. BIT_SET(PHONEDEV(xpd).oht_pcm_pass, pos);
  596. } else {
  597. LINE_DBG(SIGNAL, xpd, pos, "OHT PCM: block\n");
  598. BIT_CLR(PHONEDEV(xpd).oht_pcm_pass, pos);
  599. }
  600. CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
  601. }
  602. EXPORT_SYMBOL(oht_pcm);
  603. /*
  604. * Update our hookstate -- for PCM block/pass
  605. */
  606. void mark_offhook(xpd_t *xpd, int pos, bool to_offhook)
  607. {
  608. if (to_offhook) {
  609. LINE_DBG(SIGNAL, xpd, pos, "OFFHOOK\n");
  610. BIT_SET(PHONEDEV(xpd).offhook_state, pos);
  611. } else {
  612. LINE_DBG(SIGNAL, xpd, pos, "ONHOOK\n");
  613. BIT_CLR(PHONEDEV(xpd).offhook_state, pos);
  614. }
  615. CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
  616. }
  617. EXPORT_SYMBOL(mark_offhook);
  618. /*
  619. * Send a signalling notification to Asterisk
  620. */
  621. void notify_rxsig(xpd_t *xpd, int pos, enum dahdi_rxsig rxsig)
  622. {
  623. /*
  624. * We should not spinlock before calling dahdi_hooksig() as
  625. * it may call back into our xpp_hooksig() and cause
  626. * a nested spinlock scenario
  627. */
  628. LINE_DBG(SIGNAL, xpd, pos, "rxsig=%s\n", rxsig2str(rxsig));
  629. if (SPAN_REGISTERED(xpd))
  630. dahdi_hooksig(XPD_CHAN(xpd, pos), rxsig);
  631. }
  632. EXPORT_SYMBOL(notify_rxsig);
  633. /*
  634. * Called when hardware state changed:
  635. * - FXS -- the phone was picked up or hanged-up.
  636. * - FXO -- we answered the phone or handed-up.
  637. */
  638. void hookstate_changed(xpd_t *xpd, int pos, bool to_offhook)
  639. {
  640. BUG_ON(!xpd);
  641. mark_offhook(xpd, pos, to_offhook);
  642. if (!to_offhook) {
  643. oht_pcm(xpd, pos, 0);
  644. /*
  645. * To prevent latest PCM to stay in buffers
  646. * indefinitely, mark this channel for a
  647. * single silence transmittion.
  648. *
  649. * This bit will be cleared on the next tick.
  650. */
  651. BIT_SET(PHONEDEV(xpd).silence_pcm, pos);
  652. }
  653. notify_rxsig(xpd, pos,
  654. (to_offhook) ? DAHDI_RXSIG_OFFHOOK : DAHDI_RXSIG_ONHOOK);
  655. }
  656. EXPORT_SYMBOL(hookstate_changed);
  657. #define XPP_MAX_LEN 512
  658. /*------------------------- Dahdi Interfaces -----------------------*/
  659. /*
  660. * Called with spinlock held on chan. Must not call back
  661. * dahdi functions.
  662. */
  663. static int _xpp_open(struct dahdi_chan *chan)
  664. {
  665. xpd_t *xpd;
  666. xbus_t *xbus;
  667. int pos;
  668. int open_counter;
  669. if (!chan) {
  670. NOTICE("open called on a null chan\n");
  671. return -EINVAL;
  672. }
  673. xpd = chan->pvt;
  674. if (!xpd) {
  675. NOTICE("open called on a chan with no pvt (xpd)\n");
  676. BUG();
  677. }
  678. xbus = xpd->xbus;
  679. if (!xbus) {
  680. NOTICE("open called on a chan with no xbus\n");
  681. BUG();
  682. }
  683. pos = chan->chanpos - 1;
  684. if (!xpd->card_present) {
  685. LINE_NOTICE(xpd, pos, "Cannot open -- device not ready\n");
  686. return -ENODEV;
  687. }
  688. open_counter = atomic_inc_return(&PHONEDEV(xpd).open_counter);
  689. LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n", current->comm,
  690. current->pid, open_counter);
  691. if (PHONE_METHOD(card_open, xpd))
  692. CALL_PHONE_METHOD(card_open, xpd, pos);
  693. return 0;
  694. }
  695. int xpp_open(struct dahdi_chan *chan)
  696. {
  697. unsigned long flags;
  698. int res;
  699. spin_lock_irqsave(&chan->lock, flags);
  700. res = _xpp_open(chan);
  701. spin_unlock_irqrestore(&chan->lock, flags);
  702. return res;
  703. }
  704. EXPORT_SYMBOL(xpp_open);
  705. int xpp_close(struct dahdi_chan *chan)
  706. {
  707. xpd_t *xpd = chan->pvt;
  708. int pos = chan->chanpos - 1;
  709. int open_counter;
  710. if (PHONE_METHOD(card_close, xpd))
  711. CALL_PHONE_METHOD(card_close, xpd, pos);
  712. /* from xpp_open(): */
  713. open_counter = atomic_dec_return(&PHONEDEV(xpd).open_counter);
  714. LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n", current->comm,
  715. current->pid, open_counter);
  716. return 0;
  717. }
  718. EXPORT_SYMBOL(xpp_close);
  719. void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd)
  720. {
  721. char *extra_msg = "";
  722. if (_IOC_TYPE(cmd) == 'J')
  723. extra_msg = " (for old ZAPTEL)";
  724. XPD_NOTICE(xpd, "%s: Bad ioctl%s\n", msg, extra_msg);
  725. XPD_NOTICE(xpd, "ENOTTY: chan=%d cmd=0x%x\n", pos, cmd);
  726. XPD_NOTICE(xpd, " IOC_TYPE=0x%02X\n", _IOC_TYPE(cmd));
  727. XPD_NOTICE(xpd, " IOC_DIR=0x%02X\n", _IOC_DIR(cmd));
  728. XPD_NOTICE(xpd, " IOC_NR=%d\n", _IOC_NR(cmd));
  729. XPD_NOTICE(xpd, " IOC_SIZE=0x%02X\n", _IOC_SIZE(cmd));
  730. }
  731. EXPORT_SYMBOL(report_bad_ioctl);
  732. int xpp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long arg)
  733. {
  734. xpd_t *xpd = chan->pvt;
  735. int pos = chan->chanpos - 1;
  736. if (!xpd) {
  737. ERR("%s: channel in pos %d, was already closed. Ignore.\n",
  738. __func__, pos);
  739. return -ENODEV;
  740. }
  741. switch (cmd) {
  742. default:
  743. /* Some span-specific commands before we give up: */
  744. if (PHONE_METHOD(card_ioctl, xpd)) {
  745. return CALL_PHONE_METHOD(card_ioctl, xpd, pos, cmd,
  746. arg);
  747. }
  748. report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
  749. return -ENOTTY;
  750. }
  751. return 0;
  752. }
  753. EXPORT_SYMBOL(xpp_ioctl);
  754. int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig)
  755. {
  756. xpd_t *xpd = chan->pvt;
  757. xbus_t *xbus;
  758. int pos = chan->chanpos - 1;
  759. if (!xpd) {
  760. ERR("%s: channel in pos %d, was already closed. Ignore.\n",
  761. __func__, pos);
  762. return -ENODEV;
  763. }
  764. if (!PHONE_METHOD(card_hooksig, xpd)) {
  765. LINE_ERR(xpd, pos,
  766. "%s: No hooksig method for this channel. Ignore.\n",
  767. __func__);
  768. return -ENODEV;
  769. }
  770. xbus = xpd->xbus;
  771. BUG_ON(!xbus);
  772. DBG(SIGNAL, "Setting %s to %s (%d)\n", chan->name, txsig2str(txsig),
  773. txsig);
  774. return CALL_PHONE_METHOD(card_hooksig, xpd, pos, txsig);
  775. }
  776. EXPORT_SYMBOL(xpp_hooksig);
  777. /* Req: Set the requested chunk size. This is the unit in which you must
  778. report results for conferencing, etc */
  779. int xpp_setchunksize(struct dahdi_span *span, int chunksize);
  780. /* Enable maintenance modes */
  781. int xpp_maint(struct dahdi_span *span, int cmd)
  782. {
  783. struct phonedev *phonedev = container_of(span, struct phonedev, span);
  784. xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
  785. int ret = 0;
  786. #if 0
  787. char loopback_data[] = "THE-QUICK-BROWN-FOX-JUMPED-OVER-THE-LAZY-DOG";
  788. #endif
  789. DBG(GENERAL, "span->mainttimer=%d\n", span->mainttimer);
  790. switch (cmd) {
  791. case DAHDI_MAINT_NONE:
  792. INFO("XXX Turn off local and remote loops XXX\n");
  793. break;
  794. case DAHDI_MAINT_LOCALLOOP:
  795. INFO("XXX Turn on local loopback XXX\n");
  796. break;
  797. case DAHDI_MAINT_REMOTELOOP:
  798. INFO("XXX Turn on remote loopback XXX\n");
  799. break;
  800. case DAHDI_MAINT_LOOPUP:
  801. INFO("XXX Send loopup code XXX\n");
  802. break;
  803. case DAHDI_MAINT_LOOPDOWN:
  804. INFO("XXX Send loopdown code XXX\n");
  805. break;
  806. default:
  807. ERR("XPP: Unknown maint command: %d\n", cmd);
  808. ret = -EINVAL;
  809. break;
  810. }
  811. if (span->mainttimer || span->maintstat)
  812. update_xpd_status(xpd, DAHDI_ALARM_LOOPBACK);
  813. return ret;
  814. }
  815. EXPORT_SYMBOL(xpp_maint);
  816. #ifdef CONFIG_DAHDI_WATCHDOG
  817. /*
  818. * If the watchdog detects no received data, it will call the
  819. * watchdog routine
  820. */
  821. int xpp_watchdog(struct dahdi_span *span, int cause)
  822. {
  823. static int rate_limit;
  824. if ((rate_limit++ % 1000) == 0)
  825. DBG(GENERAL, "\n");
  826. return 0;
  827. }
  828. EXPORT_SYMBOL(xpp_watchdog);
  829. #endif
  830. /*
  831. * Hardware Echo Canceller management
  832. */
  833. static void echocan_free(struct dahdi_chan *chan,
  834. struct dahdi_echocan_state *ec)
  835. {
  836. xpd_t *xpd;
  837. xbus_t *xbus;
  838. int pos = chan->chanpos - 1;
  839. const struct echoops *echoops;
  840. xpd = chan->pvt;
  841. xbus = xpd->xbus;
  842. echoops = ECHOOPS(xbus);
  843. if (!echoops)
  844. return;
  845. LINE_DBG(GENERAL, xpd, pos, "mode=0x%X\n", ec->status.mode);
  846. CALL_EC_METHOD(ec_set, xbus, xpd, pos, 0);
  847. CALL_EC_METHOD(ec_update, xbus, xbus);
  848. put_xpd(__func__, xpd); /* aquired in xpp_echocan_create() */
  849. }
  850. static const struct dahdi_echocan_features xpp_ec_features = {
  851. };
  852. static const struct dahdi_echocan_ops xpp_ec_ops = {
  853. .echocan_free = echocan_free,
  854. };
  855. const char *xpp_echocan_name(const struct dahdi_chan *chan)
  856. {
  857. xpd_t *xpd;
  858. xbus_t *xbus;
  859. int pos;
  860. if (!chan) {
  861. NOTICE("%s(NULL)\n", __func__);
  862. return "XPP";
  863. }
  864. xpd = chan->pvt;
  865. xbus = xpd->xbus;
  866. pos = chan->chanpos - 1;
  867. LINE_DBG(GENERAL, xpd, pos, "\n");
  868. if (!ECHOOPS(xbus))
  869. return NULL;
  870. /*
  871. * quirks and limitations
  872. */
  873. if (xbus->quirks.has_fxo) {
  874. if (xbus->quirks.has_digital_span && xpd->type == XPD_TYPE_FXO) {
  875. LINE_NOTICE(xpd, pos,
  876. "quirk: give up HWEC on FXO: "
  877. "AB has digital span\n");
  878. return NULL;
  879. } else if (xbus->sync_mode != SYNC_MODE_AB
  880. && xpd->type == XPD_TYPE_FXS) {
  881. LINE_NOTICE(xpd, pos,
  882. "quirk: give up HWEC on FXS: "
  883. "AB has FXO and is sync slave\n");
  884. return NULL;
  885. }
  886. }
  887. return "XPP";
  888. }
  889. EXPORT_SYMBOL(xpp_echocan_name);
  890. int xpp_echocan_create(struct dahdi_chan *chan,
  891. struct dahdi_echocanparams *ecp,
  892. struct dahdi_echocanparam *p,
  893. struct dahdi_echocan_state **ec)
  894. {
  895. xpd_t *xpd;
  896. xbus_t *xbus;
  897. int pos;
  898. struct phonedev *phonedev;
  899. const struct echoops *echoops;
  900. int ret;
  901. xpd = chan->pvt;
  902. xbus = xpd->xbus;
  903. pos = chan->chanpos - 1;
  904. echoops = ECHOOPS(xbus);
  905. if (!echoops)
  906. return -ENODEV;
  907. phonedev = &PHONEDEV(xpd);
  908. *ec = phonedev->ec[pos];
  909. (*ec)->ops = &xpp_ec_ops;
  910. (*ec)->features = xpp_ec_features;
  911. xpd = get_xpd(__func__, xpd); /* Returned in echocan_free() */
  912. LINE_DBG(GENERAL, xpd, pos, "(tap=%d, param_count=%d)\n",
  913. ecp->tap_length, ecp->param_count);
  914. ret = CALL_EC_METHOD(ec_set, xbus, xpd, pos, 1);
  915. CALL_EC_METHOD(ec_update, xbus, xbus);
  916. return ret;
  917. }
  918. EXPORT_SYMBOL(xpp_echocan_create);
  919. void xpp_span_assigned(struct dahdi_span *span)
  920. {
  921. struct phonedev *phonedev = container_of(span, struct phonedev, span);
  922. xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
  923. XPD_INFO(xpd, "Span assigned: %d\n", span->spanno);
  924. if (xpd->card_present) {
  925. span->alarms &= ~DAHDI_ALARM_NOTOPEN;
  926. dahdi_alarm_notify(&phonedev->span);
  927. }
  928. }
  929. EXPORT_SYMBOL(xpp_span_assigned);
  930. static const struct dahdi_span_ops xpp_span_ops = {
  931. .owner = THIS_MODULE,
  932. .open = xpp_open,
  933. .close = xpp_close,
  934. .ioctl = xpp_ioctl,
  935. .maint = xpp_maint,
  936. .echocan_create = xpp_echocan_create,
  937. .echocan_name = xpp_echocan_name,
  938. .assigned = xpp_span_assigned,
  939. };
  940. static const struct dahdi_span_ops xpp_rbs_span_ops = {
  941. .owner = THIS_MODULE,
  942. .hooksig = xpp_hooksig,
  943. .open = xpp_open,
  944. .close = xpp_close,
  945. .ioctl = xpp_ioctl,
  946. .maint = xpp_maint,
  947. .echocan_create = xpp_echocan_create,
  948. .echocan_name = xpp_echocan_name,
  949. .assigned = xpp_span_assigned,
  950. };
  951. void xpd_set_spanname(xpd_t *xpd)
  952. {
  953. struct dahdi_span *span = &PHONEDEV(xpd).span;
  954. snprintf(span->name, MAX_SPANNAME, "%s/%s", xpd->xbus->busname,
  955. xpd->xpdname);
  956. /*
  957. * The "Xorcom XPD" is a prefix in one of the regexes we
  958. * use in our dahdi_genconf to match for PRI cards.
  959. * FIXME: After moving completely to sysfs, we can remove
  960. * this horseshit.
  961. */
  962. snprintf(span->desc, MAX_SPANDESC, "Xorcom XPD [%s].%d: %s",
  963. xpd->xbus->label, span->offset + 1, xpd->type_name);
  964. }
  965. EXPORT_SYMBOL(xpd_set_spanname);
  966. static void xpd_init_span(xpd_t *xpd, unsigned offset, int cn)
  967. {
  968. struct dahdi_span *span;
  969. memset(&PHONEDEV(xpd).span, 0, sizeof(struct dahdi_span));
  970. phonedev_alloc_channels(xpd, cn);
  971. span = &PHONEDEV(xpd).span;
  972. span->deflaw = DAHDI_LAW_MULAW; /* card_* drivers may override */
  973. span->channels = cn;
  974. span->chans = PHONEDEV(xpd).chans;
  975. span->flags = DAHDI_FLAG_RBS;
  976. span->offset = offset;
  977. if (PHONEDEV(xpd).phoneops->card_hooksig)
  978. span->ops = &xpp_rbs_span_ops; /* Only with RBS bits */
  979. else
  980. span->ops = &xpp_span_ops;
  981. xpd_set_spanname(xpd);
  982. list_add_tail(&span->device_node, &xpd->xbus->ddev->spans);
  983. }
  984. int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset)
  985. {
  986. xbus_t *xbus;
  987. int cn;
  988. struct phonedev *phonedev;
  989. BUG_ON(!xpd);
  990. xbus = xpd->xbus;
  991. if (!IS_PHONEDEV(xpd)) {
  992. XPD_ERR(xpd, "Not a telephony device\n");
  993. return -EBADF;
  994. }
  995. phonedev = &PHONEDEV(xpd);
  996. if (SPAN_REGISTERED(xpd)) {
  997. XPD_ERR(xpd, "Already registered\n");
  998. return -EEXIST;
  999. }
  1000. cn = PHONEDEV(xpd).channels;
  1001. xpd_init_span(xpd, offset, cn);
  1002. XPD_DBG(DEVICES, xpd, "Preregister local span %d: %d channels.\n",
  1003. offset + 1, cn);
  1004. CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 1);
  1005. return 0;
  1006. }
  1007. int xpd_dahdi_postregister(xpd_t *xpd)
  1008. {
  1009. int cn;
  1010. atomic_inc(&num_registered_spans);
  1011. atomic_inc(&PHONEDEV(xpd).dahdi_registered);
  1012. CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 1);
  1013. /*
  1014. * Update dahdi about our state:
  1015. * - Since asterisk didn't open the channel yet,
  1016. * the report is discarded anyway.
  1017. * - Our FXS driver have another notification mechanism that
  1018. * is triggered (indirectly) by the open() of the channe.
  1019. * - The real fix should be in Asterisk (to get the correct state
  1020. * after open).
  1021. */
  1022. for_each_line(xpd, cn) {
  1023. if (IS_OFFHOOK(xpd, cn))
  1024. notify_rxsig(xpd, cn, DAHDI_RXSIG_OFFHOOK);
  1025. }
  1026. return 0;
  1027. }
  1028. /*
  1029. * Try our best to make asterisk close all channels related to
  1030. * this Astribank:
  1031. * - Set span state to DAHDI_ALARM_NOTOPEN in all relevant spans.
  1032. * - Notify dahdi afterwards about spans
  1033. * (so it can see all changes at once).
  1034. * - Also send DAHDI_EVENT_REMOVED on all channels.
  1035. */
  1036. void xpd_dahdi_preunregister(xpd_t *xpd)
  1037. {
  1038. if (!xpd || !IS_PHONEDEV(xpd))
  1039. return;
  1040. XPD_DBG(DEVICES, xpd, "\n");
  1041. update_xpd_status(xpd, DAHDI_ALARM_NOTOPEN);
  1042. if (xpd->card_present)
  1043. CALL_PHONE_METHOD(card_dahdi_preregistration, xpd, 0);
  1044. /* Now notify dahdi */
  1045. if (SPAN_REGISTERED(xpd)) {
  1046. int j;
  1047. dahdi_alarm_notify(&PHONEDEV(xpd).span);
  1048. XPD_DBG(DEVICES, xpd,
  1049. "Queuing DAHDI_EVENT_REMOVED on all channels "
  1050. "to ask user to release them\n");
  1051. for (j = 0; j < PHONEDEV(xpd).span.channels; j++) {
  1052. dahdi_qevent_lock(XPD_CHAN(xpd, j),
  1053. DAHDI_EVENT_REMOVED);
  1054. }
  1055. }
  1056. }
  1057. void xpd_dahdi_postunregister(xpd_t *xpd)
  1058. {
  1059. if (!xpd || !IS_PHONEDEV(xpd))
  1060. return;
  1061. atomic_dec(&PHONEDEV(xpd).dahdi_registered);
  1062. atomic_dec(&num_registered_spans);
  1063. if (xpd->card_present)
  1064. CALL_PHONE_METHOD(card_dahdi_postregistration, xpd, 0);
  1065. }
  1066. /*------------------------- Initialization -------------------------*/
  1067. static void do_cleanup(void)
  1068. {
  1069. #ifdef CONFIG_PROC_FS
  1070. if (xpp_proc_toplevel) {
  1071. DBG(GENERAL, "Removing '%s' from proc\n", PROC_DIR);
  1072. remove_proc_entry(PROC_DIR, NULL);
  1073. xpp_proc_toplevel = NULL;
  1074. }
  1075. #endif
  1076. }
  1077. static int __init xpp_dahdi_init(void)
  1078. {
  1079. int ret = 0;
  1080. void *top = NULL;
  1081. INFO("revision %s MAX_XPDS=%d (%d*%d)\n", XPP_VERSION, MAX_XPDS,
  1082. MAX_UNIT, MAX_SUBUNIT);
  1083. #ifdef CONFIG_PROC_FS
  1084. xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL);
  1085. if (!xpp_proc_toplevel) {
  1086. ret = -EIO;
  1087. goto err;
  1088. }
  1089. top = xpp_proc_toplevel;
  1090. #endif
  1091. ret = xbus_core_init();
  1092. if (ret) {
  1093. ERR("xbus_core_init failed (%d)\n", ret);
  1094. goto err;
  1095. }
  1096. ret = xbus_pcm_init(top);
  1097. if (ret) {
  1098. ERR("xbus_pcm_init failed (%d)\n", ret);
  1099. xbus_core_shutdown();
  1100. goto err;
  1101. }
  1102. return 0;
  1103. err:
  1104. do_cleanup();
  1105. return ret;
  1106. }
  1107. static void __exit xpp_dahdi_cleanup(void)
  1108. {
  1109. xbus_pcm_shutdown();
  1110. xbus_core_shutdown();
  1111. do_cleanup();
  1112. }
  1113. MODULE_DESCRIPTION("XPP Dahdi Driver");
  1114. MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
  1115. MODULE_LICENSE("GPL");
  1116. MODULE_VERSION(XPP_VERSION);
  1117. module_init(xpp_dahdi_init);
  1118. module_exit(xpp_dahdi_cleanup);