mntfunc.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /* $Id: mntfunc.c,v 1.19.6.4 2005/01/31 12:22:20 armin Exp $
  2. *
  3. * Driver for Eicon DIVA Server ISDN cards.
  4. * Maint module
  5. *
  6. * Copyright 2000-2003 by Armin Schindler (mac@melware.de)
  7. * Copyright 2000-2003 Cytronics & Melware (info@melware.de)
  8. *
  9. * This software may be used and distributed according to the terms
  10. * of the GNU General Public License, incorporated herein by reference.
  11. */
  12. #include "platform.h"
  13. #include "di_defs.h"
  14. #include "divasync.h"
  15. #include "debug_if.h"
  16. extern char *DRIVERRELEASE_MNT;
  17. #define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
  18. #define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
  19. extern void DIVA_DIDD_Read(void *, int);
  20. static dword notify_handle;
  21. static DESCRIPTOR DAdapter;
  22. static DESCRIPTOR MAdapter;
  23. static DESCRIPTOR MaintDescriptor =
  24. { IDI_DIMAINT, 0, 0, (IDI_CALL) diva_maint_prtComp };
  25. extern int diva_os_copy_to_user(void *os_handle, void __user *dst,
  26. const void *src, int length);
  27. extern int diva_os_copy_from_user(void *os_handle, void *dst,
  28. const void __user *src, int length);
  29. static void no_printf(unsigned char *x, ...)
  30. {
  31. /* dummy debug function */
  32. }
  33. #include "debuglib.c"
  34. /*
  35. * DIDD callback function
  36. */
  37. static void *didd_callback(void *context, DESCRIPTOR *adapter,
  38. int removal)
  39. {
  40. if (adapter->type == IDI_DADAPTER) {
  41. DBG_ERR(("cb: Change in DAdapter ? Oops ?."));
  42. } else if (adapter->type == IDI_DIMAINT) {
  43. if (removal) {
  44. DbgDeregister();
  45. memset(&MAdapter, 0, sizeof(MAdapter));
  46. dprintf = no_printf;
  47. } else {
  48. memcpy(&MAdapter, adapter, sizeof(MAdapter));
  49. dprintf = (DIVA_DI_PRINTF) MAdapter.request;
  50. DbgRegister("MAINT", DRIVERRELEASE_MNT, DBG_DEFAULT);
  51. }
  52. } else if ((adapter->type > 0) && (adapter->type < 16)) {
  53. if (removal) {
  54. diva_mnt_remove_xdi_adapter(adapter);
  55. } else {
  56. diva_mnt_add_xdi_adapter(adapter);
  57. }
  58. }
  59. return (NULL);
  60. }
  61. /*
  62. * connect to didd
  63. */
  64. static int __init connect_didd(void)
  65. {
  66. int x = 0;
  67. int dadapter = 0;
  68. IDI_SYNC_REQ req;
  69. DESCRIPTOR DIDD_Table[MAX_DESCRIPTORS];
  70. DIVA_DIDD_Read(DIDD_Table, sizeof(DIDD_Table));
  71. for (x = 0; x < MAX_DESCRIPTORS; x++) {
  72. if (DIDD_Table[x].type == IDI_DADAPTER) { /* DADAPTER found */
  73. dadapter = 1;
  74. memcpy(&DAdapter, &DIDD_Table[x], sizeof(DAdapter));
  75. req.didd_notify.e.Req = 0;
  76. req.didd_notify.e.Rc =
  77. IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY;
  78. req.didd_notify.info.callback = (void *)didd_callback;
  79. req.didd_notify.info.context = NULL;
  80. DAdapter.request((ENTITY *)&req);
  81. if (req.didd_notify.e.Rc != 0xff)
  82. return (0);
  83. notify_handle = req.didd_notify.info.handle;
  84. /* Register MAINT (me) */
  85. req.didd_add_adapter.e.Req = 0;
  86. req.didd_add_adapter.e.Rc =
  87. IDI_SYNC_REQ_DIDD_ADD_ADAPTER;
  88. req.didd_add_adapter.info.descriptor =
  89. (void *) &MaintDescriptor;
  90. DAdapter.request((ENTITY *)&req);
  91. if (req.didd_add_adapter.e.Rc != 0xff)
  92. return (0);
  93. } else if ((DIDD_Table[x].type > 0)
  94. && (DIDD_Table[x].type < 16)) {
  95. diva_mnt_add_xdi_adapter(&DIDD_Table[x]);
  96. }
  97. }
  98. return (dadapter);
  99. }
  100. /*
  101. * disconnect from didd
  102. */
  103. static void __exit disconnect_didd(void)
  104. {
  105. IDI_SYNC_REQ req;
  106. req.didd_notify.e.Req = 0;
  107. req.didd_notify.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY;
  108. req.didd_notify.info.handle = notify_handle;
  109. DAdapter.request((ENTITY *)&req);
  110. req.didd_remove_adapter.e.Req = 0;
  111. req.didd_remove_adapter.e.Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER;
  112. req.didd_remove_adapter.info.p_request =
  113. (IDI_CALL) MaintDescriptor.request;
  114. DAdapter.request((ENTITY *)&req);
  115. }
  116. /*
  117. * read/write maint
  118. */
  119. int maint_read_write(void __user *buf, int count)
  120. {
  121. byte data[128];
  122. dword cmd, id, mask;
  123. int ret = 0;
  124. if (count < (3 * sizeof(dword)))
  125. return (-EFAULT);
  126. if (diva_os_copy_from_user(NULL, (void *) &data[0],
  127. buf, 3 * sizeof(dword))) {
  128. return (-EFAULT);
  129. }
  130. cmd = *(dword *)&data[0]; /* command */
  131. id = *(dword *)&data[4]; /* driver id */
  132. mask = *(dword *)&data[8]; /* mask or size */
  133. switch (cmd) {
  134. case DITRACE_CMD_GET_DRIVER_INFO:
  135. if ((ret = diva_get_driver_info(id, data, sizeof(data))) > 0) {
  136. if ((count < ret) || diva_os_copy_to_user
  137. (NULL, buf, (void *) &data[0], ret))
  138. ret = -EFAULT;
  139. } else {
  140. ret = -EINVAL;
  141. }
  142. break;
  143. case DITRACE_READ_DRIVER_DBG_MASK:
  144. if ((ret = diva_get_driver_dbg_mask(id, (byte *) data)) > 0) {
  145. if ((count < ret) || diva_os_copy_to_user
  146. (NULL, buf, (void *) &data[0], ret))
  147. ret = -EFAULT;
  148. } else {
  149. ret = -ENODEV;
  150. }
  151. break;
  152. case DITRACE_WRITE_DRIVER_DBG_MASK:
  153. if ((ret = diva_set_driver_dbg_mask(id, mask)) <= 0) {
  154. ret = -ENODEV;
  155. }
  156. break;
  157. /*
  158. Filter commands will ignore the ID due to fact that filtering affects
  159. the B- channel and Audio Tap trace levels only. Also MAINT driver will
  160. select the right trace ID by itself
  161. */
  162. case DITRACE_WRITE_SELECTIVE_TRACE_FILTER:
  163. if (!mask) {
  164. ret = diva_set_trace_filter(1, "*");
  165. } else if (mask < sizeof(data)) {
  166. if (diva_os_copy_from_user(NULL, data, (char __user *)buf + 12, mask)) {
  167. ret = -EFAULT;
  168. } else {
  169. ret = diva_set_trace_filter((int)mask, data);
  170. }
  171. } else {
  172. ret = -EINVAL;
  173. }
  174. break;
  175. case DITRACE_READ_SELECTIVE_TRACE_FILTER:
  176. if ((ret = diva_get_trace_filter(sizeof(data), data)) > 0) {
  177. if (diva_os_copy_to_user(NULL, buf, data, ret))
  178. ret = -EFAULT;
  179. } else {
  180. ret = -ENODEV;
  181. }
  182. break;
  183. case DITRACE_READ_TRACE_ENTRY:{
  184. diva_os_spin_lock_magic_t old_irql;
  185. word size;
  186. diva_dbg_entry_head_t *pmsg;
  187. byte *pbuf;
  188. if (!(pbuf = diva_os_malloc(0, mask))) {
  189. return (-ENOMEM);
  190. }
  191. for (;;) {
  192. if (!(pmsg =
  193. diva_maint_get_message(&size, &old_irql))) {
  194. break;
  195. }
  196. if (size > mask) {
  197. diva_maint_ack_message(0, &old_irql);
  198. ret = -EINVAL;
  199. break;
  200. }
  201. ret = size;
  202. memcpy(pbuf, pmsg, size);
  203. diva_maint_ack_message(1, &old_irql);
  204. if ((count < size) ||
  205. diva_os_copy_to_user(NULL, buf, (void *) pbuf, size))
  206. ret = -EFAULT;
  207. break;
  208. }
  209. diva_os_free(0, pbuf);
  210. }
  211. break;
  212. case DITRACE_READ_TRACE_ENTRYS:{
  213. diva_os_spin_lock_magic_t old_irql;
  214. word size;
  215. diva_dbg_entry_head_t *pmsg;
  216. byte *pbuf = NULL;
  217. int written = 0;
  218. if (mask < 4096) {
  219. ret = -EINVAL;
  220. break;
  221. }
  222. if (!(pbuf = diva_os_malloc(0, mask))) {
  223. return (-ENOMEM);
  224. }
  225. for (;;) {
  226. if (!(pmsg =
  227. diva_maint_get_message(&size, &old_irql))) {
  228. break;
  229. }
  230. if ((size + 8) > mask) {
  231. diva_maint_ack_message(0, &old_irql);
  232. break;
  233. }
  234. /*
  235. Write entry length
  236. */
  237. pbuf[written++] = (byte) size;
  238. pbuf[written++] = (byte) (size >> 8);
  239. pbuf[written++] = 0;
  240. pbuf[written++] = 0;
  241. /*
  242. Write message
  243. */
  244. memcpy(&pbuf[written], pmsg, size);
  245. diva_maint_ack_message(1, &old_irql);
  246. written += size;
  247. mask -= (size + 4);
  248. }
  249. pbuf[written++] = 0;
  250. pbuf[written++] = 0;
  251. pbuf[written++] = 0;
  252. pbuf[written++] = 0;
  253. if ((count < written) || diva_os_copy_to_user(NULL, buf, (void *) pbuf, written)) {
  254. ret = -EFAULT;
  255. } else {
  256. ret = written;
  257. }
  258. diva_os_free(0, pbuf);
  259. }
  260. break;
  261. default:
  262. ret = -EINVAL;
  263. }
  264. return (ret);
  265. }
  266. /*
  267. * init
  268. */
  269. int __init mntfunc_init(int *buffer_length, void **buffer,
  270. unsigned long diva_dbg_mem)
  271. {
  272. if (*buffer_length < 64) {
  273. *buffer_length = 64;
  274. }
  275. if (*buffer_length > 512) {
  276. *buffer_length = 512;
  277. }
  278. *buffer_length *= 1024;
  279. if (diva_dbg_mem) {
  280. *buffer = (void *) diva_dbg_mem;
  281. } else {
  282. while ((*buffer_length >= (64 * 1024))
  283. &&
  284. (!(*buffer = diva_os_malloc(0, *buffer_length)))) {
  285. *buffer_length -= 1024;
  286. }
  287. if (!*buffer) {
  288. DBG_ERR(("init: Can not alloc trace buffer"));
  289. return (0);
  290. }
  291. }
  292. if (diva_maint_init(*buffer, *buffer_length, (diva_dbg_mem == 0))) {
  293. if (!diva_dbg_mem) {
  294. diva_os_free(0, *buffer);
  295. }
  296. DBG_ERR(("init: maint init failed"));
  297. return (0);
  298. }
  299. if (!connect_didd()) {
  300. DBG_ERR(("init: failed to connect to DIDD."));
  301. diva_maint_finit();
  302. if (!diva_dbg_mem) {
  303. diva_os_free(0, *buffer);
  304. }
  305. return (0);
  306. }
  307. return (1);
  308. }
  309. /*
  310. * exit
  311. */
  312. void __exit mntfunc_finit(void)
  313. {
  314. void *buffer;
  315. int i = 100;
  316. DbgDeregister();
  317. while (diva_mnt_shutdown_xdi_adapters() && i--) {
  318. diva_os_sleep(10);
  319. }
  320. disconnect_didd();
  321. if ((buffer = diva_maint_finit())) {
  322. diva_os_free(0, buffer);
  323. }
  324. memset(&MAdapter, 0, sizeof(MAdapter));
  325. dprintf = no_printf;
  326. }