xbus-sysfs.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041
  1. /*
  2. * Written by Oron Peled <oron@actcom.co.il>
  3. * Copyright (C) 2004-2006, Xorcom
  4. *
  5. * All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. *
  21. */
  22. #include <linux/version.h>
  23. #include <linux/kernel.h>
  24. #include <linux/module.h>
  25. #include <linux/errno.h>
  26. #include <linux/proc_fs.h>
  27. #ifdef PROTOCOL_DEBUG
  28. #include <linux/ctype.h>
  29. #endif
  30. #include <linux/workqueue.h>
  31. #include <linux/device.h>
  32. #include <linux/delay.h> /* for msleep() to debug */
  33. #include <linux/sched.h>
  34. #include "xpd.h"
  35. #include "xpp_dahdi.h"
  36. #include "xbus-core.h"
  37. #include "dahdi_debug.h"
  38. static const char rcsid[] = "$Id$";
  39. /* Command line parameters */
  40. extern int debug;
  41. /*--------- xpp driver attributes -*/
  42. static ssize_t sync_show(struct device_driver *driver, char *buf)
  43. {
  44. DBG(SYNC, "\n");
  45. return fill_sync_string(buf, PAGE_SIZE);
  46. }
  47. static ssize_t sync_store(struct device_driver *driver, const char *buf,
  48. size_t count)
  49. {
  50. /* DBG(SYNC, "%s\n", buf); */
  51. return exec_sync_command(buf, count);
  52. }
  53. #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
  54. static struct driver_attribute xpp_attrs[] = {
  55. __ATTR(sync, S_IRUGO | S_IWUSR, sync_show, sync_store),
  56. __ATTR_NULL,
  57. };
  58. #else
  59. static DRIVER_ATTR_RW(sync);
  60. static struct attribute *xpp_attrs[] = {
  61. &driver_attr_sync.attr,
  62. NULL,
  63. };
  64. ATTRIBUTE_GROUPS(xpp);
  65. #endif
  66. /*--------- Sysfs Bus handling ----*/
  67. static DEVICE_ATTR_READER(xbus_state_show, dev, buf)
  68. {
  69. xbus_t *xbus;
  70. int ret;
  71. xbus = dev_to_xbus(dev);
  72. ret = XBUS_STATE(xbus);
  73. ret = snprintf(buf, PAGE_SIZE, "%s (%d)\n", xbus_statename(ret), ret);
  74. return ret;
  75. }
  76. static DEVICE_ATTR_WRITER(xbus_state_store, dev, buf, count)
  77. {
  78. xbus_t *xbus;
  79. xbus = dev_to_xbus(dev);
  80. XBUS_DBG(GENERAL, xbus, "%s\n", buf);
  81. if (strncmp(buf, "stop", 4) == 0)
  82. xbus_deactivate(xbus);
  83. else if (XBUS_IS(xbus, IDLE) && strncmp(buf, "start", 5) == 0)
  84. xbus_activate(xbus);
  85. else {
  86. XBUS_NOTICE(xbus,
  87. "%s: Illegal action %s in state %s. Ignored.\n",
  88. __func__, buf, xbus_statename(XBUS_STATE(xbus)));
  89. return -EINVAL;
  90. }
  91. return count;
  92. }
  93. static DEVICE_ATTR_READER(status_show, dev, buf)
  94. {
  95. xbus_t *xbus;
  96. int ret;
  97. xbus = dev_to_xbus(dev);
  98. ret =
  99. snprintf(buf, PAGE_SIZE, "%s\n",
  100. (XBUS_FLAGS(xbus, CONNECTED)) ? "connected" : "missing");
  101. return ret;
  102. }
  103. static DEVICE_ATTR_READER(timing_show, dev, buf)
  104. {
  105. xbus_t *xbus;
  106. struct xpp_drift *driftinfo;
  107. int len = 0;
  108. struct timeval now;
  109. do_gettimeofday(&now);
  110. xbus = dev_to_xbus(dev);
  111. driftinfo = &xbus->drift;
  112. len +=
  113. snprintf(buf + len, PAGE_SIZE - len, "%-3s",
  114. sync_mode_name(xbus->sync_mode));
  115. if (xbus->sync_mode == SYNC_MODE_PLL) {
  116. len +=
  117. snprintf(buf + len, PAGE_SIZE - len,
  118. " %5d: lost (%4d,%4d) : ", xbus->ticker.cycle,
  119. driftinfo->lost_ticks, driftinfo->lost_tick_count);
  120. len +=
  121. snprintf(buf + len, PAGE_SIZE - len,
  122. "DRIFT %3d %ld sec ago", xbus->sync_adjustment,
  123. (xbus->pll_updated_at ==
  124. 0) ? 0 : now.tv_sec - xbus->pll_updated_at);
  125. }
  126. len += snprintf(buf + len, PAGE_SIZE - len, "\n");
  127. return len;
  128. }
  129. #ifdef SAMPLE_TICKS
  130. /*
  131. * tick sampling: Measure offset from reference ticker:
  132. * - Recording start when writing to:
  133. * /sys/bus/astribanks/devices/xbus-??/samples
  134. * - Recording ends when filling SAMPLE_SIZE ticks
  135. * - Results are read from the same sysfs file.
  136. * - Trying to read/write during recording, returns -EBUSY.
  137. */
  138. static DEVICE_ATTR_READER(samples_show, dev, buf)
  139. {
  140. xbus_t *xbus;
  141. int len = 0;
  142. int i;
  143. xbus = dev_to_xbus(dev);
  144. if (xbus->sample_running)
  145. return -EBUSY;
  146. for (i = 0; i < SAMPLE_SIZE; i++) {
  147. if (len > PAGE_SIZE - 20)
  148. break;
  149. len +=
  150. snprintf(buf + len, PAGE_SIZE - len, "%d\n",
  151. xbus->sample_ticks[i]);
  152. }
  153. return len;
  154. }
  155. static DEVICE_ATTR_WRITER(samples_store, dev, buf, count)
  156. {
  157. xbus_t *xbus;
  158. xbus = dev_to_xbus(dev);
  159. if (xbus->sample_running)
  160. return -EBUSY;
  161. memset(xbus->sample_ticks, 0, sizeof(*xbus->sample_ticks));
  162. xbus->sample_pos = 0;
  163. xbus->sample_running = 1;
  164. return count;
  165. }
  166. #endif
  167. /*
  168. * Clear statistics
  169. */
  170. static DEVICE_ATTR_WRITER(cls_store, dev, buf, count)
  171. {
  172. xbus_t *xbus;
  173. struct xpp_drift *driftinfo;
  174. xbus = dev_to_xbus(dev);
  175. driftinfo = &xbus->drift;
  176. driftinfo->lost_ticks = 0;
  177. driftinfo->lost_tick_count = 0;
  178. xbus->min_tx_sync = INT_MAX;
  179. xbus->max_tx_sync = 0;
  180. xbus->min_rx_sync = INT_MAX;
  181. xbus->max_rx_sync = 0;
  182. #ifdef SAMPLE_TICKS
  183. memset(xbus->sample_ticks, 0, sizeof(*xbus->sample_ticks));
  184. #endif
  185. return count;
  186. }
  187. static DEVICE_ATTR_READER(waitfor_xpds_show, dev, buf)
  188. {
  189. xbus_t *xbus;
  190. int len;
  191. xbus = dev_to_xbus(dev);
  192. len = waitfor_xpds(xbus, buf);
  193. return len;
  194. }
  195. static DEVICE_ATTR_READER(refcount_xbus_show, dev, buf)
  196. {
  197. xbus_t *xbus;
  198. int len;
  199. xbus = dev_to_xbus(dev);
  200. len = sprintf(buf, "%d\n", refcount_xbus(xbus));
  201. return len;
  202. }
  203. static DEVICE_ATTR_READER(driftinfo_show, dev, buf)
  204. {
  205. xbus_t *xbus;
  206. struct xpp_drift *di;
  207. struct xpp_ticker *ticker;
  208. struct timeval now;
  209. int len = 0;
  210. int hours;
  211. int minutes;
  212. int seconds;
  213. int speed_range;
  214. int uframes_inaccuracy;
  215. int i;
  216. xbus = dev_to_xbus(dev);
  217. di = &xbus->drift;
  218. ticker = &xbus->ticker;
  219. /*
  220. * Calculate lost ticks time
  221. */
  222. do_gettimeofday(&now);
  223. seconds = now.tv_sec - di->last_lost_tick.tv.tv_sec;
  224. minutes = seconds / 60;
  225. seconds = seconds % 60;
  226. hours = minutes / 60;
  227. minutes = minutes % 60;
  228. len += snprintf(buf + len, PAGE_SIZE - len,
  229. "%-15s: %8d (was %d:%02d:%02d ago)\n", "lost_ticks",
  230. di->lost_ticks, hours, minutes, seconds);
  231. speed_range = abs(di->max_speed - di->min_speed);
  232. uframes_inaccuracy = di->sync_inaccuracy / 125;
  233. len += snprintf(buf + len, PAGE_SIZE - len,
  234. "%-15s: %8d ", "instability",
  235. speed_range + uframes_inaccuracy);
  236. if (xbus->sync_mode == SYNC_MODE_AB) {
  237. buf[len++] = '-';
  238. } else {
  239. for (i = 0;
  240. len < PAGE_SIZE - 1
  241. && i < speed_range + uframes_inaccuracy; i++)
  242. buf[len++] = '#';
  243. }
  244. buf[len++] = '\n';
  245. len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d (uframes)\n",
  246. "inaccuracy", uframes_inaccuracy);
  247. len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n",
  248. "speed_range", speed_range);
  249. #define SHOW(ptr, item) \
  250. do { \
  251. len += snprintf(buf + len, PAGE_SIZE - len, \
  252. "%-15s: %8d\n", #item, (ptr)->item); \
  253. } while (0)
  254. SHOW(xbus, sync_adjustment);
  255. len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n",
  256. "offset (usec)", di->offset_prev);
  257. SHOW(di, offset_range);
  258. len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %8d\n",
  259. "best_speed", (di->max_speed + di->min_speed) / 2);
  260. SHOW(di, min_speed);
  261. SHOW(di, max_speed);
  262. SHOW(ticker, cycle);
  263. SHOW(ticker, tick_period);
  264. SHOW(ticker, count);
  265. #undef SHOW
  266. return len;
  267. }
  268. #define xbus_attr(field, format_string) \
  269. static ssize_t \
  270. field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
  271. { \
  272. xbus_t *xbus; \
  273. xbus = dev_to_xbus(dev); \
  274. return sprintf(buf, format_string, xbus->field); \
  275. }
  276. xbus_attr(connector, "%s\n");
  277. xbus_attr(label, "%s\n");
  278. static DEVICE_ATTR_WRITER(dahdi_registration_store, dev, buf, count)
  279. {
  280. xbus_t *xbus;
  281. int dahdi_reg;
  282. int ret;
  283. xbus = dev_to_xbus(dev);
  284. if (!xbus)
  285. return -ENODEV;
  286. ret = sscanf(buf, "%d", &dahdi_reg);
  287. if (ret != 1)
  288. return -EINVAL;
  289. if (dahdi_reg) {
  290. ret = xbus_register_dahdi_device(xbus);
  291. if (ret < 0) {
  292. XBUS_ERR(xbus,
  293. "xbus_register_dahdi_device() failed (ret = %d)\n",
  294. ret);
  295. return ret;
  296. }
  297. } else {
  298. xbus_unregister_dahdi_device(xbus);
  299. }
  300. return count;
  301. }
  302. static DEVICE_ATTR_READER(dahdi_registration_show, dev, buf)
  303. {
  304. xbus_t *xbus;
  305. int len;
  306. xbus = dev_to_xbus(dev);
  307. len = sprintf(buf, "%d\n", xbus_is_registered(xbus));
  308. return len;
  309. }
  310. static struct device_attribute xbus_dev_attrs[] = {
  311. __ATTR_RO(connector),
  312. __ATTR_RO(label),
  313. __ATTR_RO(status),
  314. __ATTR_RO(timing),
  315. __ATTR_RO(refcount_xbus),
  316. __ATTR_RO(waitfor_xpds),
  317. __ATTR_RO(driftinfo),
  318. __ATTR(cls, S_IWUSR, NULL, cls_store),
  319. __ATTR(xbus_state, S_IRUGO | S_IWUSR, xbus_state_show,
  320. xbus_state_store),
  321. #ifdef SAMPLE_TICKS
  322. __ATTR(samples, S_IWUSR | S_IRUGO, samples_show, samples_store),
  323. #endif
  324. __ATTR(dahdi_registration, S_IRUGO | S_IWUSR,
  325. dahdi_registration_show,
  326. dahdi_registration_store),
  327. __ATTR_NULL,
  328. };
  329. static int astribank_match(struct device *dev, struct device_driver *driver)
  330. {
  331. DBG(DEVICES, "SYSFS MATCH: dev->bus_id = %s, driver->name = %s\n",
  332. dev_name(dev), driver->name);
  333. return 1;
  334. }
  335. #define XBUS_VAR_BLOCK \
  336. do { \
  337. XBUS_ADD_UEVENT_VAR("XPP_INIT_DIR=%s", initdir); \
  338. XBUS_ADD_UEVENT_VAR("XBUS_NUM=%02d", xbus->num); \
  339. XBUS_ADD_UEVENT_VAR("XBUS_NAME=%s", xbus->busname); \
  340. } while (0)
  341. #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
  342. #define XBUS_ADD_UEVENT_VAR(fmt, val...) \
  343. do { \
  344. int err = add_uevent_var(envp, num_envp, &i, \
  345. buffer, buffer_size, &len, \
  346. fmt, val); \
  347. if (err) \
  348. return err; \
  349. } while (0)
  350. static int astribank_uevent(struct device *dev, char **envp, int num_envp,
  351. char *buffer, int buffer_size)
  352. {
  353. xbus_t *xbus;
  354. int i = 0;
  355. int len = 0;
  356. extern char *initdir;
  357. if (!dev)
  358. return -ENODEV;
  359. xbus = dev_to_xbus(dev);
  360. DBG(GENERAL, "SYFS bus_id=%s xbus=%s\n", dev_name(dev), xbus->busname);
  361. XBUS_VAR_BLOCK;
  362. envp[i] = NULL;
  363. return 0;
  364. }
  365. #else
  366. #define XBUS_ADD_UEVENT_VAR(fmt, val...) \
  367. do { \
  368. int err = add_uevent_var(kenv, fmt, val); \
  369. if (err) \
  370. return err; \
  371. } while (0)
  372. static int astribank_uevent(struct device *dev, struct kobj_uevent_env *kenv)
  373. {
  374. xbus_t *xbus;
  375. extern char *initdir;
  376. if (!dev)
  377. return -ENODEV;
  378. xbus = dev_to_xbus(dev);
  379. DBG(GENERAL, "SYFS bus_id=%s xbus=%s\n", dev_name(dev), xbus->busname);
  380. XBUS_VAR_BLOCK;
  381. return 0;
  382. }
  383. #endif
  384. void astribank_uevent_send(xbus_t *xbus, enum kobject_action act)
  385. {
  386. struct kobject *kobj;
  387. kobj = &xbus->astribank.kobj;
  388. XBUS_DBG(DEVICES, xbus, "SYFS bus_id=%s action=%d\n",
  389. dev_name(&xbus->astribank), act);
  390. kobject_uevent(kobj, act);
  391. }
  392. static void astribank_release(struct device *dev)
  393. {
  394. xbus_t *xbus;
  395. BUG_ON(!dev);
  396. xbus = dev_to_xbus(dev);
  397. if (XBUS_FLAGS(xbus, CONNECTED)) {
  398. XBUS_ERR(xbus, "Try to release CONNECTED device.\n");
  399. BUG();
  400. }
  401. if (!XBUS_IS(xbus, IDLE) && !XBUS_IS(xbus, FAIL)
  402. && !XBUS_IS(xbus, DEACTIVATED)) {
  403. XBUS_ERR(xbus, "Try to release in state %s\n",
  404. xbus_statename(XBUS_STATE(xbus)));
  405. BUG();
  406. }
  407. XBUS_INFO(xbus, "[%s] Astribank Release\n", xbus->label);
  408. xbus_free(xbus);
  409. }
  410. static struct bus_type toplevel_bus_type = {
  411. .name = "astribanks",
  412. .match = astribank_match,
  413. .uevent = astribank_uevent,
  414. .dev_attrs = xbus_dev_attrs,
  415. #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
  416. .drv_attrs = xpp_attrs,
  417. #else
  418. .drv_groups = xpp_groups,
  419. #endif
  420. };
  421. static int astribank_probe(struct device *dev)
  422. {
  423. xbus_t *xbus;
  424. xbus = dev_to_xbus(dev);
  425. XBUS_DBG(DEVICES, xbus, "SYSFS\n");
  426. return 0;
  427. }
  428. static int astribank_remove(struct device *dev)
  429. {
  430. xbus_t *xbus;
  431. xbus = dev_to_xbus(dev);
  432. XBUS_INFO(xbus, "[%s] Atribank Remove\n", xbus->label);
  433. return 0;
  434. }
  435. static struct device_driver xpp_driver = {
  436. .name = "xppdrv",
  437. .bus = &toplevel_bus_type,
  438. .probe = astribank_probe,
  439. .remove = astribank_remove,
  440. .owner = THIS_MODULE
  441. };
  442. /*--------- Sysfs XPD handling ----*/
  443. static DEVICE_ATTR_READER(chipregs_show, dev, buf)
  444. {
  445. xpd_t *xpd;
  446. unsigned long flags;
  447. reg_cmd_t *regs;
  448. bool do_datah;
  449. char datah_str[50];
  450. int len = 0;
  451. BUG_ON(!dev);
  452. xpd = dev_to_xpd(dev);
  453. if (!xpd)
  454. return -ENODEV;
  455. spin_lock_irqsave(&xpd->lock, flags);
  456. regs = &xpd->last_reply;
  457. len += sprintf(buf + len,
  458. "# Writing bad data to this file may damage your hardware!\n");
  459. len += sprintf(buf + len, "# Consult firmware docs first\n");
  460. len += sprintf(buf + len, "#\n");
  461. do_datah = REG_FIELD(regs, do_datah) ? 1 : 0;
  462. if (do_datah) {
  463. snprintf(datah_str, ARRAY_SIZE(datah_str), "\t%02X",
  464. REG_FIELD(regs, data_high));
  465. } else
  466. datah_str[0] = '\0';
  467. if (REG_FIELD(regs, do_subreg)) {
  468. len +=
  469. sprintf(buf + len, "#CH\tOP\tReg.\tSub\tDL%s\n",
  470. (do_datah) ? "\tDH" : "");
  471. len +=
  472. sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n",
  473. regs->portnum, REG_FIELD(regs, regnum),
  474. REG_FIELD(regs, subreg), REG_FIELD(regs, data_low),
  475. datah_str);
  476. } else {
  477. len +=
  478. sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n",
  479. (do_datah) ? "\tDH" : "");
  480. len +=
  481. sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->portnum,
  482. REG_FIELD(regs, regnum), REG_FIELD(regs, data_low),
  483. datah_str);
  484. }
  485. spin_unlock_irqrestore(&xpd->lock, flags);
  486. return len;
  487. }
  488. static DEVICE_ATTR_WRITER(chipregs_store, dev, buf, count)
  489. {
  490. xpd_t *xpd;
  491. const char *p;
  492. char tmp[MAX_PROC_WRITE];
  493. int i;
  494. int ret;
  495. BUG_ON(!dev);
  496. xpd = dev_to_xpd(dev);
  497. //XPD_DBG(GENERAL, xpd, "%s\n", buf);
  498. if (!xpd)
  499. return -ENODEV;
  500. p = buf;
  501. while ((p - buf) < count) {
  502. i = strcspn(p, "\r\n");
  503. if (i > 0) {
  504. if (i >= MAX_PROC_WRITE) {
  505. XPD_NOTICE(xpd, "Command too long (%d chars)\n",
  506. i);
  507. return -E2BIG;
  508. }
  509. memcpy(tmp, p, i);
  510. tmp[i] = '\0';
  511. ret = parse_chip_command(xpd, tmp);
  512. if (ret < 0) {
  513. XPD_NOTICE(xpd,
  514. "Failed writing command: '%s'\n",
  515. tmp);
  516. return ret;
  517. }
  518. }
  519. p += i + 1;
  520. /* Don't flood command_queue */
  521. if (xframe_queue_count(&xpd->xbus->command_queue) > 5)
  522. msleep(6);
  523. }
  524. return count;
  525. }
  526. static DEVICE_ATTR_READER(blink_show, dev, buf)
  527. {
  528. xpd_t *xpd;
  529. unsigned long flags;
  530. int len = 0;
  531. BUG_ON(!dev);
  532. xpd = dev_to_xpd(dev);
  533. if (!xpd)
  534. return -ENODEV;
  535. spin_lock_irqsave(&xpd->lock, flags);
  536. len += sprintf(buf, "0x%lX\n", xpd->blink_mode);
  537. spin_unlock_irqrestore(&xpd->lock, flags);
  538. return len;
  539. }
  540. static DEVICE_ATTR_WRITER(blink_store, dev, buf, count)
  541. {
  542. xpd_t *xpd;
  543. char *endp;
  544. unsigned long blink;
  545. BUG_ON(!dev);
  546. xpd = dev_to_xpd(dev);
  547. //XPD_DBG(GENERAL, xpd, "%s\n", buf);
  548. if (!xpd)
  549. return -ENODEV;
  550. blink = simple_strtoul(buf, &endp, 0);
  551. if (*endp != '\0' && *endp != '\n' && *endp != '\r')
  552. return -EINVAL;
  553. if (blink > 0xFFFF)
  554. return -EINVAL;
  555. XPD_DBG(GENERAL, xpd, "BLINK channels: 0x%lX\n", blink);
  556. xpd->blink_mode = blink;
  557. return count;
  558. }
  559. static DEVICE_ATTR_READER(span_show, dev, buf)
  560. {
  561. xpd_t *xpd;
  562. unsigned long flags;
  563. int len = 0;
  564. BUG_ON(!dev);
  565. xpd = dev_to_xpd(dev);
  566. if (!xpd)
  567. return -ENODEV;
  568. spin_lock_irqsave(&xpd->lock, flags);
  569. len +=
  570. sprintf(buf, "%d\n",
  571. SPAN_REGISTERED(xpd) ? PHONEDEV(xpd).span.spanno : 0);
  572. spin_unlock_irqrestore(&xpd->lock, flags);
  573. return len;
  574. }
  575. /*
  576. * For backward compatibility with old dahdi-tools
  577. * Remove after dahdi_registration is upgraded
  578. */
  579. static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
  580. {
  581. xpd_t *xpd;
  582. int dahdi_reg;
  583. int ret;
  584. BUG_ON(!dev);
  585. xpd = dev_to_xpd(dev);
  586. if (!xpd)
  587. return -ENODEV;
  588. ret = sscanf(buf, "%d", &dahdi_reg);
  589. if (ret != 1)
  590. return -EINVAL;
  591. if (!XBUS_IS(xpd->xbus, READY))
  592. return -ENODEV;
  593. XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use assigned-spans)\n",
  594. (dahdi_reg) ? "register" : "unregister");
  595. if (dahdi_reg)
  596. xbus_register_dahdi_device(xpd->xbus);
  597. else
  598. xbus_unregister_dahdi_device(xpd->xbus);
  599. return count;
  600. }
  601. static DEVICE_ATTR_READER(type_show, dev, buf)
  602. {
  603. xpd_t *xpd;
  604. int len = 0;
  605. BUG_ON(!dev);
  606. xpd = dev_to_xpd(dev);
  607. if (!xpd)
  608. return -ENODEV;
  609. len += sprintf(buf, "%s\n", xpd->type_name);
  610. return len;
  611. }
  612. static DEVICE_ATTR_READER(offhook_show, dev, buf)
  613. {
  614. xpd_t *xpd;
  615. int len = 0;
  616. int i;
  617. BUG_ON(!dev);
  618. xpd = dev_to_xpd(dev);
  619. if (!xpd)
  620. return -ENODEV;
  621. for_each_line(xpd, i) {
  622. len += sprintf(buf + len, "%d ", IS_OFFHOOK(xpd, i));
  623. }
  624. if (len)
  625. len--; /* backout last space */
  626. len += sprintf(buf + len, "\n");
  627. return len;
  628. }
  629. static DEVICE_ATTR_READER(timing_priority_show, dev, buf)
  630. {
  631. xpd_t *xpd;
  632. unsigned long flags;
  633. int len = 0;
  634. BUG_ON(!dev);
  635. xpd = dev_to_xpd(dev);
  636. if (!xpd)
  637. return -ENODEV;
  638. spin_lock_irqsave(&xpd->lock, flags);
  639. len += sprintf(buf + len, "%d\n", PHONEDEV(xpd).timing_priority);
  640. spin_unlock_irqrestore(&xpd->lock, flags);
  641. return len;
  642. }
  643. static DEVICE_ATTR_READER(refcount_xpd_show, dev, buf)
  644. {
  645. xpd_t *xpd;
  646. int len = 0;
  647. BUG_ON(!dev);
  648. xpd = dev_to_xpd(dev);
  649. if (!xpd)
  650. return -ENODEV;
  651. len += sprintf(buf + len, "%d\n", refcount_xpd(xpd));
  652. return len;
  653. }
  654. static int xpd_match(struct device *dev, struct device_driver *driver)
  655. {
  656. struct xpd_driver *xpd_driver;
  657. xpd_t *xpd;
  658. xpd_driver = driver_to_xpd_driver(driver);
  659. xpd = dev_to_xpd(dev);
  660. if (xpd_driver->type != xpd->type) {
  661. XPD_DBG(DEVICES, xpd,
  662. "SYSFS match fail: xpd->type = %d, "
  663. "xpd_driver->type = %d\n",
  664. xpd->type, xpd_driver->type);
  665. return 0;
  666. }
  667. XPD_DBG(DEVICES, xpd,
  668. "SYSFS MATCH: type=%d dev->bus_id = %s, driver->name = %s\n",
  669. xpd->type, dev_name(dev), driver->name);
  670. return 1;
  671. }
  672. static struct device_attribute xpd_dev_attrs[] = {
  673. __ATTR(chipregs, S_IRUGO | S_IWUSR, chipregs_show, chipregs_store),
  674. __ATTR(blink, S_IRUGO | S_IWUSR, blink_show, blink_store),
  675. __ATTR(span, S_IRUGO | S_IWUSR, span_show, span_store),
  676. __ATTR_RO(type),
  677. __ATTR_RO(offhook),
  678. __ATTR_RO(timing_priority),
  679. __ATTR_RO(refcount_xpd),
  680. __ATTR_NULL,
  681. };
  682. static struct bus_type xpd_type = {
  683. .name = "xpds",
  684. .match = xpd_match,
  685. .dev_attrs = xpd_dev_attrs,
  686. };
  687. int xpd_driver_register(struct device_driver *driver)
  688. {
  689. int ret;
  690. DBG(DEVICES, "%s\n", driver->name);
  691. driver->bus = &xpd_type;
  692. if ((ret = driver_register(driver)) < 0) {
  693. ERR("%s: driver_register(%s) failed. Error number %d", __func__,
  694. driver->name, ret);
  695. }
  696. return ret;
  697. }
  698. EXPORT_SYMBOL(xpd_driver_register);
  699. void xpd_driver_unregister(struct device_driver *driver)
  700. {
  701. DBG(DEVICES, "%s\n", driver->name);
  702. driver_unregister(driver);
  703. }
  704. EXPORT_SYMBOL(xpd_driver_unregister);
  705. static void xpd_release(struct device *dev)
  706. {
  707. xpd_t *xpd;
  708. BUG_ON(!dev);
  709. xpd = dev_to_xpd(dev);
  710. XPD_DBG(DEVICES, xpd, "SYSFS\n");
  711. xpd_remove(xpd);
  712. }
  713. int xpd_device_register(xbus_t *xbus, xpd_t *xpd)
  714. {
  715. struct device *dev = &xpd->xpd_dev;
  716. int ret;
  717. XPD_DBG(DEVICES, xpd, "SYSFS\n");
  718. dev->bus = &xpd_type;
  719. dev->parent = &xbus->astribank;
  720. dev_set_name(dev, "%02d:%1x:%1x", xbus->num, xpd->addr.unit,
  721. xpd->addr.subunit);
  722. dev_set_drvdata(dev, xpd);
  723. dev->release = xpd_release;
  724. ret = device_register(dev);
  725. if (ret) {
  726. XPD_ERR(xpd, "%s: device_register failed: %d\n", __func__, ret);
  727. return ret;
  728. }
  729. return 0;
  730. }
  731. void xpd_device_unregister(xpd_t *xpd)
  732. {
  733. xbus_t *xbus;
  734. struct device *dev;
  735. xbus = xpd->xbus;
  736. BUG_ON(!xbus);
  737. XPD_DBG(DEVICES, xpd, "SYSFS\n");
  738. dev = &xpd->xpd_dev;
  739. if (!dev_get_drvdata(dev))
  740. return;
  741. BUG_ON(dev_get_drvdata(dev) != xpd);
  742. device_unregister(dev);
  743. dev_set_drvdata(dev, NULL);
  744. }
  745. static DEVICE_ATTR_READER(echocancel_show, dev, buf)
  746. {
  747. xpd_t *xpd;
  748. unsigned long flags;
  749. int len = 0;
  750. xpp_line_t ec_mask = 0;
  751. int i;
  752. int ret;
  753. BUG_ON(!dev);
  754. xpd = dev_to_xpd(dev);
  755. if (!xpd)
  756. return -ENODEV;
  757. if (!ECHOOPS(xpd->xbus))
  758. return -ENODEV;
  759. spin_lock_irqsave(&xpd->lock, flags);
  760. for (i = 0; i < PHONEDEV(xpd).channels; i++) {
  761. ret = CALL_EC_METHOD(ec_get, xpd->xbus, xpd, i);
  762. if (ret < 0) {
  763. LINE_ERR(xpd, i, "ec_get failed\n");
  764. len = -ENODEV;
  765. goto out;
  766. }
  767. if (ret)
  768. ec_mask |= (1 << i);
  769. }
  770. len += sprintf(buf, "0x%08X\n", ec_mask);
  771. out:
  772. spin_unlock_irqrestore(&xpd->lock, flags);
  773. return len;
  774. }
  775. static DEVICE_ATTR_WRITER(echocancel_store, dev, buf, count)
  776. {
  777. xpd_t *xpd;
  778. char *endp;
  779. unsigned long mask;
  780. int channels;
  781. int ret;
  782. BUG_ON(!dev);
  783. xpd = dev_to_xpd(dev);
  784. XPD_DBG(GENERAL, xpd, "%s\n", buf);
  785. if (!xpd)
  786. return -ENODEV;
  787. if (!ECHOOPS(xpd->xbus)) {
  788. XPD_ERR(xpd, "No echo canceller in this XBUS\n");
  789. return -ENODEV;
  790. }
  791. if (!IS_PHONEDEV(xpd)) {
  792. XPD_ERR(xpd, "Not a phone device\n");
  793. return -ENODEV;
  794. }
  795. channels = PHONEDEV(xpd).channels;
  796. mask = simple_strtoul(buf, &endp, 0);
  797. if (*endp != '\0' && *endp != '\n' && *endp != '\r') {
  798. XPD_ERR(xpd, "Too many channels: %d\n", channels);
  799. return -EINVAL;
  800. }
  801. if (mask != 0 && __ffs(mask) > channels) {
  802. XPD_ERR(xpd,
  803. "Channel mask (0x%lX) larger than "
  804. "available channels (%d)\n",
  805. mask, channels);
  806. return -EINVAL;
  807. }
  808. XPD_DBG(GENERAL, xpd, "ECHOCANCEL channels: 0x%lX\n", mask);
  809. ret = CALL_PHONE_METHOD(echocancel_setmask, xpd, mask);
  810. if (ret < 0) {
  811. XPD_ERR(xpd, "echocancel_setmask failed\n");
  812. return ret;
  813. }
  814. return count;
  815. }
  816. static DEVICE_ATTR(echocancel, S_IRUGO | S_IWUSR, echocancel_show,
  817. echocancel_store);
  818. int echocancel_xpd(xpd_t *xpd, int on)
  819. {
  820. int ret;
  821. XPD_DBG(GENERAL, xpd, "echocancel_xpd(%s)\n", (on) ? "on" : "off");
  822. if (!on) {
  823. device_remove_file(xpd->echocancel, &dev_attr_echocancel);
  824. return 0;
  825. }
  826. ret = device_create_file(&xpd->xpd_dev, &dev_attr_echocancel);
  827. if (ret)
  828. XPD_ERR(xpd, "%s: device_create_file(echocancel) failed: %d\n",
  829. __func__, ret);
  830. return ret;
  831. }
  832. EXPORT_SYMBOL(echocancel_xpd);
  833. /*--------- Sysfs Device handling ----*/
  834. void xbus_sysfs_transport_remove(xbus_t *xbus)
  835. {
  836. struct device *astribank;
  837. BUG_ON(!xbus);
  838. XBUS_DBG(DEVICES, xbus, "\n");
  839. astribank = &xbus->astribank;
  840. sysfs_remove_link(&astribank->kobj, "transport");
  841. }
  842. int xbus_sysfs_transport_create(xbus_t *xbus)
  843. {
  844. struct device *astribank;
  845. struct device *transport_device;
  846. int ret = 0;
  847. BUG_ON(!xbus);
  848. XBUS_DBG(DEVICES, xbus, "\n");
  849. astribank = &xbus->astribank;
  850. BUG_ON(!astribank);
  851. transport_device = xbus->transport.transport_device;
  852. if (!transport_device) {
  853. XBUS_ERR(xbus, "%s: Missing transport_device\n", __func__);
  854. return -ENODEV;
  855. }
  856. ret =
  857. sysfs_create_link(&astribank->kobj, &transport_device->kobj,
  858. "transport");
  859. if (ret < 0) {
  860. XBUS_ERR(xbus, "%s: sysfs_create_link failed: %d\n", __func__,
  861. ret);
  862. dev_set_drvdata(astribank, NULL);
  863. }
  864. return ret;
  865. }
  866. void xbus_sysfs_remove(xbus_t *xbus)
  867. {
  868. struct device *astribank;
  869. BUG_ON(!xbus);
  870. astribank = &xbus->astribank;
  871. if (!dev_get_drvdata(astribank)) {
  872. XBUS_NOTICE(xbus, "%s: already removed\n", __func__);
  873. return;
  874. }
  875. XBUS_DBG(DEVICES, xbus, "going to unregister: refcount=%d\n",
  876. atomic_read(&astribank->kobj.kref.refcount));
  877. BUG_ON(dev_get_drvdata(astribank) != xbus);
  878. device_unregister(astribank);
  879. dev_set_drvdata(astribank, NULL);
  880. }
  881. int xbus_sysfs_create(xbus_t *xbus)
  882. {
  883. struct device *astribank;
  884. int ret = 0;
  885. BUG_ON(!xbus);
  886. astribank = &xbus->astribank;
  887. XBUS_DBG(DEVICES, xbus, "\n");
  888. astribank->bus = &toplevel_bus_type;
  889. astribank->parent = xbus->transport.transport_device;
  890. dev_set_name(astribank, "xbus-%02d", xbus->num);
  891. dev_set_drvdata(astribank, xbus);
  892. astribank->release = astribank_release;
  893. ret = device_register(astribank);
  894. if (ret) {
  895. XBUS_ERR(xbus, "%s: device_register failed: %d\n", __func__,
  896. ret);
  897. dev_set_drvdata(astribank, NULL);
  898. }
  899. return ret;
  900. }
  901. int __init xpp_driver_init(void)
  902. {
  903. int ret;
  904. DBG(DEVICES, "SYSFS\n");
  905. if ((ret = bus_register(&toplevel_bus_type)) < 0) {
  906. ERR("%s: bus_register(%s) failed. Error number %d", __func__,
  907. toplevel_bus_type.name, ret);
  908. goto failed_toplevel;
  909. }
  910. if ((ret = driver_register(&xpp_driver)) < 0) {
  911. ERR("%s: driver_register(%s) failed. Error number %d", __func__,
  912. xpp_driver.name, ret);
  913. goto failed_xpp_driver;
  914. }
  915. if ((ret = bus_register(&xpd_type)) < 0) {
  916. ERR("%s: bus_register(%s) failed. Error number %d", __func__,
  917. xpd_type.name, ret);
  918. goto failed_xpd_bus;
  919. }
  920. return 0;
  921. failed_xpd_bus:
  922. driver_unregister(&xpp_driver);
  923. failed_xpp_driver:
  924. bus_unregister(&toplevel_bus_type);
  925. failed_toplevel:
  926. return ret;
  927. }
  928. void xpp_driver_exit(void)
  929. {
  930. DBG(DEVICES, "SYSFS\n");
  931. bus_unregister(&xpd_type);
  932. driver_unregister(&xpp_driver);
  933. bus_unregister(&toplevel_bus_type);
  934. }