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