diva.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. // SPDX-License-Identifier: GPL-2.0
  2. /* $Id: diva.c,v 1.21.4.1 2004/05/08 14:33:43 armin Exp $ */
  3. #define CARDTYPE_H_WANT_DATA 1
  4. #define CARDTYPE_H_WANT_IDI_DATA 0
  5. #define CARDTYPE_H_WANT_RESOURCE_DATA 0
  6. #define CARDTYPE_H_WANT_FILE_DATA 0
  7. #include "platform.h"
  8. #include "debuglib.h"
  9. #include "cardtype.h"
  10. #include "pc.h"
  11. #include "di_defs.h"
  12. #include "di.h"
  13. #include "io.h"
  14. #include "pc_maint.h"
  15. #include "xdi_msg.h"
  16. #include "xdi_adapter.h"
  17. #include "diva_pci.h"
  18. #include "diva.h"
  19. #ifdef CONFIG_ISDN_DIVAS_PRIPCI
  20. #include "os_pri.h"
  21. #endif
  22. #ifdef CONFIG_ISDN_DIVAS_BRIPCI
  23. #include "os_bri.h"
  24. #include "os_4bri.h"
  25. #endif
  26. PISDN_ADAPTER IoAdapters[MAX_ADAPTER];
  27. extern IDI_CALL Requests[MAX_ADAPTER];
  28. extern int create_adapter_proc(diva_os_xdi_adapter_t *a);
  29. extern void remove_adapter_proc(diva_os_xdi_adapter_t *a);
  30. #define DivaIdiReqFunc(N) \
  31. static void DivaIdiRequest##N(ENTITY *e) \
  32. { if (IoAdapters[N]) (*IoAdapters[N]->DIRequest)(IoAdapters[N], e); }
  33. /*
  34. ** Create own 32 Adapters
  35. */
  36. DivaIdiReqFunc(0)
  37. DivaIdiReqFunc(1)
  38. DivaIdiReqFunc(2)
  39. DivaIdiReqFunc(3)
  40. DivaIdiReqFunc(4)
  41. DivaIdiReqFunc(5)
  42. DivaIdiReqFunc(6)
  43. DivaIdiReqFunc(7)
  44. DivaIdiReqFunc(8)
  45. DivaIdiReqFunc(9)
  46. DivaIdiReqFunc(10)
  47. DivaIdiReqFunc(11)
  48. DivaIdiReqFunc(12)
  49. DivaIdiReqFunc(13)
  50. DivaIdiReqFunc(14)
  51. DivaIdiReqFunc(15)
  52. DivaIdiReqFunc(16)
  53. DivaIdiReqFunc(17)
  54. DivaIdiReqFunc(18)
  55. DivaIdiReqFunc(19)
  56. DivaIdiReqFunc(20)
  57. DivaIdiReqFunc(21)
  58. DivaIdiReqFunc(22)
  59. DivaIdiReqFunc(23)
  60. DivaIdiReqFunc(24)
  61. DivaIdiReqFunc(25)
  62. DivaIdiReqFunc(26)
  63. DivaIdiReqFunc(27)
  64. DivaIdiReqFunc(28)
  65. DivaIdiReqFunc(29)
  66. DivaIdiReqFunc(30)
  67. DivaIdiReqFunc(31)
  68. /*
  69. ** LOCALS
  70. */
  71. static LIST_HEAD(adapter_queue);
  72. typedef struct _diva_get_xlog {
  73. word command;
  74. byte req;
  75. byte rc;
  76. byte data[sizeof(struct mi_pc_maint)];
  77. } diva_get_xlog_t;
  78. typedef struct _diva_supported_cards_info {
  79. int CardOrdinal;
  80. diva_init_card_proc_t init_card;
  81. } diva_supported_cards_info_t;
  82. static diva_supported_cards_info_t divas_supported_cards[] = {
  83. #ifdef CONFIG_ISDN_DIVAS_PRIPCI
  84. /*
  85. PRI Cards
  86. */
  87. {CARDTYPE_DIVASRV_P_30M_PCI, diva_pri_init_card},
  88. /*
  89. PRI Rev.2 Cards
  90. */
  91. {CARDTYPE_DIVASRV_P_30M_V2_PCI, diva_pri_init_card},
  92. /*
  93. PRI Rev.2 VoIP Cards
  94. */
  95. {CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI, diva_pri_init_card},
  96. #endif
  97. #ifdef CONFIG_ISDN_DIVAS_BRIPCI
  98. /*
  99. 4BRI Rev 1 Cards
  100. */
  101. {CARDTYPE_DIVASRV_Q_8M_PCI, diva_4bri_init_card},
  102. {CARDTYPE_DIVASRV_VOICE_Q_8M_PCI, diva_4bri_init_card},
  103. /*
  104. 4BRI Rev 2 Cards
  105. */
  106. {CARDTYPE_DIVASRV_Q_8M_V2_PCI, diva_4bri_init_card},
  107. {CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI, diva_4bri_init_card},
  108. /*
  109. 4BRI Based BRI Rev 2 Cards
  110. */
  111. {CARDTYPE_DIVASRV_B_2M_V2_PCI, diva_4bri_init_card},
  112. {CARDTYPE_DIVASRV_B_2F_PCI, diva_4bri_init_card},
  113. {CARDTYPE_DIVASRV_VOICE_B_2M_V2_PCI, diva_4bri_init_card},
  114. /*
  115. BRI
  116. */
  117. {CARDTYPE_MAESTRA_PCI, diva_bri_init_card},
  118. #endif
  119. /*
  120. EOL
  121. */
  122. {-1}
  123. };
  124. static void diva_init_request_array(void);
  125. static void *divas_create_pci_card(int handle, void *pci_dev_handle);
  126. static diva_os_spin_lock_t adapter_lock;
  127. static int diva_find_free_adapters(int base, int nr)
  128. {
  129. int i;
  130. for (i = 0; i < nr; i++) {
  131. if (IoAdapters[base + i]) {
  132. return (-1);
  133. }
  134. }
  135. return (0);
  136. }
  137. static diva_os_xdi_adapter_t *diva_q_get_next(struct list_head *what)
  138. {
  139. diva_os_xdi_adapter_t *a = NULL;
  140. if (what && (what->next != &adapter_queue))
  141. a = list_entry(what->next, diva_os_xdi_adapter_t, link);
  142. return (a);
  143. }
  144. /* --------------------------------------------------------------------------
  145. Add card to the card list
  146. -------------------------------------------------------------------------- */
  147. void *diva_driver_add_card(void *pdev, unsigned long CardOrdinal)
  148. {
  149. diva_os_spin_lock_magic_t old_irql;
  150. diva_os_xdi_adapter_t *pdiva, *pa;
  151. int i, j, max, nr;
  152. for (i = 0; divas_supported_cards[i].CardOrdinal != -1; i++) {
  153. if (divas_supported_cards[i].CardOrdinal == CardOrdinal) {
  154. if (!(pdiva = divas_create_pci_card(i, pdev))) {
  155. return NULL;
  156. }
  157. switch (CardOrdinal) {
  158. case CARDTYPE_DIVASRV_Q_8M_PCI:
  159. case CARDTYPE_DIVASRV_VOICE_Q_8M_PCI:
  160. case CARDTYPE_DIVASRV_Q_8M_V2_PCI:
  161. case CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI:
  162. max = MAX_ADAPTER - 4;
  163. nr = 4;
  164. break;
  165. default:
  166. max = MAX_ADAPTER;
  167. nr = 1;
  168. }
  169. diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
  170. for (i = 0; i < max; i++) {
  171. if (!diva_find_free_adapters(i, nr)) {
  172. pdiva->controller = i + 1;
  173. pdiva->xdi_adapter.ANum = pdiva->controller;
  174. IoAdapters[i] = &pdiva->xdi_adapter;
  175. diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
  176. create_adapter_proc(pdiva); /* add adapter to proc file system */
  177. DBG_LOG(("add %s:%d",
  178. CardProperties
  179. [CardOrdinal].Name,
  180. pdiva->controller))
  181. diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
  182. pa = pdiva;
  183. for (j = 1; j < nr; j++) { /* slave adapters, if any */
  184. pa = diva_q_get_next(&pa->link);
  185. if (pa && !pa->interface.cleanup_adapter_proc) {
  186. pa->controller = i + 1 + j;
  187. pa->xdi_adapter.ANum = pa->controller;
  188. IoAdapters[i + j] = &pa->xdi_adapter;
  189. diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
  190. DBG_LOG(("add slave adapter (%d)",
  191. pa->controller))
  192. create_adapter_proc(pa); /* add adapter to proc file system */
  193. diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add card");
  194. } else {
  195. DBG_ERR(("slave adapter problem"))
  196. break;
  197. }
  198. }
  199. diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
  200. return (pdiva);
  201. }
  202. }
  203. diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add card");
  204. /*
  205. Not able to add adapter - remove it and return error
  206. */
  207. DBG_ERR(("can not alloc request array"))
  208. diva_driver_remove_card(pdiva);
  209. return NULL;
  210. }
  211. }
  212. return NULL;
  213. }
  214. /* --------------------------------------------------------------------------
  215. Called on driver load, MAIN, main, DriverEntry
  216. -------------------------------------------------------------------------- */
  217. int divasa_xdi_driver_entry(void)
  218. {
  219. diva_os_initialize_spin_lock(&adapter_lock, "adapter");
  220. memset(&IoAdapters[0], 0x00, sizeof(IoAdapters));
  221. diva_init_request_array();
  222. return (0);
  223. }
  224. /* --------------------------------------------------------------------------
  225. Remove adapter from list
  226. -------------------------------------------------------------------------- */
  227. static diva_os_xdi_adapter_t *get_and_remove_from_queue(void)
  228. {
  229. diva_os_spin_lock_magic_t old_irql;
  230. diva_os_xdi_adapter_t *a = NULL;
  231. diva_os_enter_spin_lock(&adapter_lock, &old_irql, "driver_unload");
  232. if (!list_empty(&adapter_queue)) {
  233. a = list_entry(adapter_queue.next, diva_os_xdi_adapter_t, link);
  234. list_del(adapter_queue.next);
  235. }
  236. diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload");
  237. return (a);
  238. }
  239. /* --------------------------------------------------------------------------
  240. Remove card from the card list
  241. -------------------------------------------------------------------------- */
  242. void diva_driver_remove_card(void *pdiva)
  243. {
  244. diva_os_spin_lock_magic_t old_irql;
  245. diva_os_xdi_adapter_t *a[4];
  246. diva_os_xdi_adapter_t *pa;
  247. int i;
  248. pa = a[0] = (diva_os_xdi_adapter_t *) pdiva;
  249. a[1] = a[2] = a[3] = NULL;
  250. diva_os_enter_spin_lock(&adapter_lock, &old_irql, "remode adapter");
  251. for (i = 1; i < 4; i++) {
  252. if ((pa = diva_q_get_next(&pa->link))
  253. && !pa->interface.cleanup_adapter_proc) {
  254. a[i] = pa;
  255. } else {
  256. break;
  257. }
  258. }
  259. for (i = 0; ((i < 4) && a[i]); i++) {
  260. list_del(&a[i]->link);
  261. }
  262. diva_os_leave_spin_lock(&adapter_lock, &old_irql, "driver_unload");
  263. (*(a[0]->interface.cleanup_adapter_proc)) (a[0]);
  264. for (i = 0; i < 4; i++) {
  265. if (a[i]) {
  266. if (a[i]->controller) {
  267. DBG_LOG(("remove adapter (%d)",
  268. a[i]->controller)) IoAdapters[a[i]->controller - 1] = NULL;
  269. remove_adapter_proc(a[i]);
  270. }
  271. diva_os_free(0, a[i]);
  272. }
  273. }
  274. }
  275. /* --------------------------------------------------------------------------
  276. Create diva PCI adapter and init internal adapter structures
  277. -------------------------------------------------------------------------- */
  278. static void *divas_create_pci_card(int handle, void *pci_dev_handle)
  279. {
  280. diva_supported_cards_info_t *pI = &divas_supported_cards[handle];
  281. diva_os_spin_lock_magic_t old_irql;
  282. diva_os_xdi_adapter_t *a;
  283. DBG_LOG(("found %d-%s", pI->CardOrdinal, CardProperties[pI->CardOrdinal].Name))
  284. if (!(a = (diva_os_xdi_adapter_t *) diva_os_malloc(0, sizeof(*a)))) {
  285. DBG_ERR(("A: can't alloc adapter"));
  286. return NULL;
  287. }
  288. memset(a, 0x00, sizeof(*a));
  289. a->CardIndex = handle;
  290. a->CardOrdinal = pI->CardOrdinal;
  291. a->Bus = DIVAS_XDI_ADAPTER_BUS_PCI;
  292. a->xdi_adapter.cardType = a->CardOrdinal;
  293. a->resources.pci.bus = diva_os_get_pci_bus(pci_dev_handle);
  294. a->resources.pci.func = diva_os_get_pci_func(pci_dev_handle);
  295. a->resources.pci.hdev = pci_dev_handle;
  296. /*
  297. Add master adapter first, so slave adapters will receive higher
  298. numbers as master adapter
  299. */
  300. diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
  301. list_add_tail(&a->link, &adapter_queue);
  302. diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
  303. if ((*(pI->init_card)) (a)) {
  304. diva_os_enter_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
  305. list_del(&a->link);
  306. diva_os_leave_spin_lock(&adapter_lock, &old_irql, "found_pci_card");
  307. diva_os_free(0, a);
  308. DBG_ERR(("A: can't get adapter resources"));
  309. return NULL;
  310. }
  311. return (a);
  312. }
  313. /* --------------------------------------------------------------------------
  314. Called on driver unload FINIT, finit, Unload
  315. -------------------------------------------------------------------------- */
  316. void divasa_xdi_driver_unload(void)
  317. {
  318. diva_os_xdi_adapter_t *a;
  319. while ((a = get_and_remove_from_queue())) {
  320. if (a->interface.cleanup_adapter_proc) {
  321. (*(a->interface.cleanup_adapter_proc)) (a);
  322. }
  323. if (a->controller) {
  324. IoAdapters[a->controller - 1] = NULL;
  325. remove_adapter_proc(a);
  326. }
  327. diva_os_free(0, a);
  328. }
  329. diva_os_destroy_spin_lock(&adapter_lock, "adapter");
  330. }
  331. /*
  332. ** Receive and process command from user mode utility
  333. */
  334. void *diva_xdi_open_adapter(void *os_handle, const void __user *src,
  335. int length, void *mptr,
  336. divas_xdi_copy_from_user_fn_t cp_fn)
  337. {
  338. diva_xdi_um_cfg_cmd_t *msg = (diva_xdi_um_cfg_cmd_t *)mptr;
  339. diva_os_xdi_adapter_t *a = NULL;
  340. diva_os_spin_lock_magic_t old_irql;
  341. struct list_head *tmp;
  342. if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
  343. DBG_ERR(("A: A(?) open, msg too small (%d < %d)",
  344. length, sizeof(diva_xdi_um_cfg_cmd_t)))
  345. return NULL;
  346. }
  347. if ((*cp_fn) (os_handle, msg, src, sizeof(*msg)) <= 0) {
  348. DBG_ERR(("A: A(?) open, write error"))
  349. return NULL;
  350. }
  351. diva_os_enter_spin_lock(&adapter_lock, &old_irql, "open_adapter");
  352. list_for_each(tmp, &adapter_queue) {
  353. a = list_entry(tmp, diva_os_xdi_adapter_t, link);
  354. if (a->controller == (int)msg->adapter)
  355. break;
  356. a = NULL;
  357. }
  358. diva_os_leave_spin_lock(&adapter_lock, &old_irql, "open_adapter");
  359. if (!a) {
  360. DBG_ERR(("A: A(%d) open, adapter not found", msg->adapter))
  361. }
  362. return (a);
  363. }
  364. /*
  365. ** Easy cleanup mailbox status
  366. */
  367. void diva_xdi_close_adapter(void *adapter, void *os_handle)
  368. {
  369. diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
  370. a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
  371. if (a->xdi_mbox.data) {
  372. diva_os_free(0, a->xdi_mbox.data);
  373. a->xdi_mbox.data = NULL;
  374. }
  375. }
  376. int
  377. diva_xdi_write(void *adapter, void *os_handle, const void __user *src,
  378. int length, void *mptr,
  379. divas_xdi_copy_from_user_fn_t cp_fn)
  380. {
  381. diva_xdi_um_cfg_cmd_t *msg = (diva_xdi_um_cfg_cmd_t *)mptr;
  382. diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
  383. void *data;
  384. if (a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY) {
  385. DBG_ERR(("A: A(%d) write, mbox busy", a->controller))
  386. return (-1);
  387. }
  388. if (length < sizeof(diva_xdi_um_cfg_cmd_t)) {
  389. DBG_ERR(("A: A(%d) write, message too small (%d < %d)",
  390. a->controller, length,
  391. sizeof(diva_xdi_um_cfg_cmd_t)))
  392. return (-3);
  393. }
  394. if (!(data = diva_os_malloc(0, length))) {
  395. DBG_ERR(("A: A(%d) write, ENOMEM", a->controller))
  396. return (-2);
  397. }
  398. if (msg) {
  399. *(diva_xdi_um_cfg_cmd_t *)data = *msg;
  400. length = (*cp_fn) (os_handle, (char *)data + sizeof(*msg),
  401. src + sizeof(*msg), length - sizeof(*msg));
  402. } else {
  403. length = (*cp_fn) (os_handle, data, src, length);
  404. }
  405. if (length > 0) {
  406. if ((*(a->interface.cmd_proc))
  407. (a, (diva_xdi_um_cfg_cmd_t *) data, length)) {
  408. length = -3;
  409. }
  410. } else {
  411. DBG_ERR(("A: A(%d) write error (%d)", a->controller,
  412. length))
  413. }
  414. diva_os_free(0, data);
  415. return (length);
  416. }
  417. /*
  418. ** Write answers to user mode utility, if any
  419. */
  420. int
  421. diva_xdi_read(void *adapter, void *os_handle, void __user *dst,
  422. int max_length, divas_xdi_copy_to_user_fn_t cp_fn)
  423. {
  424. diva_os_xdi_adapter_t *a = (diva_os_xdi_adapter_t *) adapter;
  425. int ret;
  426. if (!(a->xdi_mbox.status & DIVA_XDI_MBOX_BUSY)) {
  427. DBG_ERR(("A: A(%d) rx mbox empty", a->controller))
  428. return (-1);
  429. }
  430. if (!a->xdi_mbox.data) {
  431. a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
  432. DBG_ERR(("A: A(%d) rx ENOMEM", a->controller))
  433. return (-2);
  434. }
  435. if (max_length < a->xdi_mbox.data_length) {
  436. DBG_ERR(("A: A(%d) rx buffer too short(%d < %d)",
  437. a->controller, max_length,
  438. a->xdi_mbox.data_length))
  439. return (-3);
  440. }
  441. ret = (*cp_fn) (os_handle, dst, a->xdi_mbox.data,
  442. a->xdi_mbox.data_length);
  443. if (ret > 0) {
  444. diva_os_free(0, a->xdi_mbox.data);
  445. a->xdi_mbox.data = NULL;
  446. a->xdi_mbox.status &= ~DIVA_XDI_MBOX_BUSY;
  447. }
  448. return (ret);
  449. }
  450. irqreturn_t diva_os_irq_wrapper(int irq, void *context)
  451. {
  452. diva_os_xdi_adapter_t *a = context;
  453. diva_xdi_clear_interrupts_proc_t clear_int_proc;
  454. if (!a || !a->xdi_adapter.diva_isr_handler)
  455. return IRQ_NONE;
  456. if ((clear_int_proc = a->clear_interrupts_proc)) {
  457. (*clear_int_proc) (a);
  458. a->clear_interrupts_proc = NULL;
  459. return IRQ_HANDLED;
  460. }
  461. (*(a->xdi_adapter.diva_isr_handler)) (&a->xdi_adapter);
  462. return IRQ_HANDLED;
  463. }
  464. static void diva_init_request_array(void)
  465. {
  466. Requests[0] = DivaIdiRequest0;
  467. Requests[1] = DivaIdiRequest1;
  468. Requests[2] = DivaIdiRequest2;
  469. Requests[3] = DivaIdiRequest3;
  470. Requests[4] = DivaIdiRequest4;
  471. Requests[5] = DivaIdiRequest5;
  472. Requests[6] = DivaIdiRequest6;
  473. Requests[7] = DivaIdiRequest7;
  474. Requests[8] = DivaIdiRequest8;
  475. Requests[9] = DivaIdiRequest9;
  476. Requests[10] = DivaIdiRequest10;
  477. Requests[11] = DivaIdiRequest11;
  478. Requests[12] = DivaIdiRequest12;
  479. Requests[13] = DivaIdiRequest13;
  480. Requests[14] = DivaIdiRequest14;
  481. Requests[15] = DivaIdiRequest15;
  482. Requests[16] = DivaIdiRequest16;
  483. Requests[17] = DivaIdiRequest17;
  484. Requests[18] = DivaIdiRequest18;
  485. Requests[19] = DivaIdiRequest19;
  486. Requests[20] = DivaIdiRequest20;
  487. Requests[21] = DivaIdiRequest21;
  488. Requests[22] = DivaIdiRequest22;
  489. Requests[23] = DivaIdiRequest23;
  490. Requests[24] = DivaIdiRequest24;
  491. Requests[25] = DivaIdiRequest25;
  492. Requests[26] = DivaIdiRequest26;
  493. Requests[27] = DivaIdiRequest27;
  494. Requests[28] = DivaIdiRequest28;
  495. Requests[29] = DivaIdiRequest29;
  496. Requests[30] = DivaIdiRequest30;
  497. Requests[31] = DivaIdiRequest31;
  498. }
  499. void diva_xdi_display_adapter_features(int card)
  500. {
  501. dword features;
  502. if (!card || ((card - 1) >= MAX_ADAPTER) || !IoAdapters[card - 1]) {
  503. return;
  504. }
  505. card--;
  506. features = IoAdapters[card]->Properties.Features;
  507. DBG_LOG(("FEATURES FOR ADAPTER: %d", card + 1))
  508. DBG_LOG((" DI_FAX3 : %s",
  509. (features & DI_FAX3) ? "Y" : "N"))
  510. DBG_LOG((" DI_MODEM : %s",
  511. (features & DI_MODEM) ? "Y" : "N"))
  512. DBG_LOG((" DI_POST : %s",
  513. (features & DI_POST) ? "Y" : "N"))
  514. DBG_LOG((" DI_V110 : %s",
  515. (features & DI_V110) ? "Y" : "N"))
  516. DBG_LOG((" DI_V120 : %s",
  517. (features & DI_V120) ? "Y" : "N"))
  518. DBG_LOG((" DI_POTS : %s",
  519. (features & DI_POTS) ? "Y" : "N"))
  520. DBG_LOG((" DI_CODEC : %s",
  521. (features & DI_CODEC) ? "Y" : "N"))
  522. DBG_LOG((" DI_MANAGE : %s",
  523. (features & DI_MANAGE) ? "Y" : "N"))
  524. DBG_LOG((" DI_V_42 : %s",
  525. (features & DI_V_42) ? "Y" : "N"))
  526. DBG_LOG((" DI_EXTD_FAX : %s",
  527. (features & DI_EXTD_FAX) ? "Y" : "N"))
  528. DBG_LOG((" DI_AT_PARSER : %s",
  529. (features & DI_AT_PARSER) ? "Y" : "N"))
  530. DBG_LOG((" DI_VOICE_OVER_IP : %s",
  531. (features & DI_VOICE_OVER_IP) ? "Y" : "N"))
  532. }
  533. void diva_add_slave_adapter(diva_os_xdi_adapter_t *a)
  534. {
  535. diva_os_spin_lock_magic_t old_irql;
  536. diva_os_enter_spin_lock(&adapter_lock, &old_irql, "add_slave");
  537. list_add_tail(&a->link, &adapter_queue);
  538. diva_os_leave_spin_lock(&adapter_lock, &old_irql, "add_slave");
  539. }
  540. int diva_card_read_xlog(diva_os_xdi_adapter_t *a)
  541. {
  542. diva_get_xlog_t *req;
  543. byte *data;
  544. if (!a->xdi_adapter.Initialized || !a->xdi_adapter.DIRequest) {
  545. return (-1);
  546. }
  547. if (!(data = diva_os_malloc(0, sizeof(struct mi_pc_maint)))) {
  548. return (-1);
  549. }
  550. memset(data, 0x00, sizeof(struct mi_pc_maint));
  551. if (!(req = diva_os_malloc(0, sizeof(*req)))) {
  552. diva_os_free(0, data);
  553. return (-1);
  554. }
  555. req->command = 0x0400;
  556. req->req = LOG;
  557. req->rc = 0x00;
  558. (*(a->xdi_adapter.DIRequest)) (&a->xdi_adapter, (ENTITY *) req);
  559. if (!req->rc || req->req) {
  560. diva_os_free(0, data);
  561. diva_os_free(0, req);
  562. return (-1);
  563. }
  564. memcpy(data, &req->req, sizeof(struct mi_pc_maint));
  565. diva_os_free(0, req);
  566. a->xdi_mbox.data_length = sizeof(struct mi_pc_maint);
  567. a->xdi_mbox.data = data;
  568. a->xdi_mbox.status = DIVA_XDI_MBOX_BUSY;
  569. return (0);
  570. }
  571. void xdiFreeFile(void *handle)
  572. {
  573. }