1 /* $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
17 #include "xdi_adapter.h"
21 #ifdef CONFIG_ISDN_DIVAS_PRIPCI
24 #ifdef CONFIG_ISDN_DIVAS_BRIPCI
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
);
34 #define DivaIdiReqFunc(N) \
35 static void DivaIdiRequest##N(ENTITY *e) \
36 { if ( IoAdapters[N] ) (* IoAdapters[N]->DIRequest)(IoAdapters[N], e) ; }
39 ** Create own 32 Adapters
79 static LIST_HEAD(adapter_queue
);
81 typedef struct _diva_get_xlog
{
85 byte data
[sizeof(struct mi_pc_maint
)];
88 typedef struct _diva_supported_cards_info
{
90 diva_init_card_proc_t init_card
;
91 } diva_supported_cards_info_t
;
93 static diva_supported_cards_info_t divas_supported_cards
[] = {
94 #ifdef CONFIG_ISDN_DIVAS_PRIPCI
98 {CARDTYPE_DIVASRV_P_30M_PCI
, diva_pri_init_card
},
102 {CARDTYPE_DIVASRV_P_30M_V2_PCI
, diva_pri_init_card
},
106 {CARDTYPE_DIVASRV_VOICE_P_30M_V2_PCI
, diva_pri_init_card
},
108 #ifdef CONFIG_ISDN_DIVAS_BRIPCI
112 {CARDTYPE_DIVASRV_Q_8M_PCI
, diva_4bri_init_card
},
113 {CARDTYPE_DIVASRV_VOICE_Q_8M_PCI
, diva_4bri_init_card
},
117 {CARDTYPE_DIVASRV_Q_8M_V2_PCI
, diva_4bri_init_card
},
118 {CARDTYPE_DIVASRV_VOICE_Q_8M_V2_PCI
, diva_4bri_init_card
},
120 4BRI Based BRI Rev 2 Cards
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
},
128 {CARDTYPE_MAESTRA_PCI
, diva_bri_init_card
},
137 static void diva_init_request_array(void);
138 static void *divas_create_pci_card(int handle
, void *pci_dev_handle
);
140 static diva_os_spin_lock_t adapter_lock
;
142 static int diva_find_free_adapters(int base
, int nr
)
146 for (i
= 0; i
< nr
; i
++) {
147 if (IoAdapters
[base
+ i
]) {
155 static diva_os_xdi_adapter_t
*diva_q_get_next(struct list_head
* what
)
157 diva_os_xdi_adapter_t
*a
= NULL
;
159 if (what
&& (what
->next
!= &adapter_queue
))
160 a
= list_entry(what
->next
, diva_os_xdi_adapter_t
, link
);
165 /* --------------------------------------------------------------------------
166 Add card to the card list
167 -------------------------------------------------------------------------- */
168 void *diva_driver_add_card(void *pdev
, unsigned long CardOrdinal
)
170 diva_os_spin_lock_magic_t old_irql
;
171 diva_os_xdi_adapter_t
*pdiva
, *pa
;
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
))) {
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;
193 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "add card");
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 */
203 DBG_LOG(("add %s:%d",
208 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "add card");
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)",
219 create_adapter_proc(pa
); /* add adapter to proc file system */
220 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "add card");
222 DBG_ERR(("slave adapter problem"))
227 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "add card");
232 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "add card");
235 Not able to add adapter - remove it and return error
237 DBG_ERR(("can not alloc request array"))
238 diva_driver_remove_card(pdiva
);
247 /* --------------------------------------------------------------------------
248 Called on driver load, MAIN, main, DriverEntry
249 -------------------------------------------------------------------------- */
250 int divasa_xdi_driver_entry(void)
252 diva_os_initialize_spin_lock(&adapter_lock
, "adapter");
253 memset(&IoAdapters
[0], 0x00, sizeof(IoAdapters
));
254 diva_init_request_array();
259 /* --------------------------------------------------------------------------
260 Remove adapter from list
261 -------------------------------------------------------------------------- */
262 static diva_os_xdi_adapter_t
*get_and_remove_from_queue(void)
264 diva_os_spin_lock_magic_t old_irql
;
265 diva_os_xdi_adapter_t
*a
= NULL
;
267 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "driver_unload");
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
);
274 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "driver_unload");
278 /* --------------------------------------------------------------------------
279 Remove card from the card list
280 -------------------------------------------------------------------------- */
281 void diva_driver_remove_card(void *pdiva
)
283 diva_os_spin_lock_magic_t old_irql
;
284 diva_os_xdi_adapter_t
*a
[4];
285 diva_os_xdi_adapter_t
*pa
;
288 pa
= a
[0] = (diva_os_xdi_adapter_t
*) pdiva
;
289 a
[1] = a
[2] = a
[3] = NULL
;
291 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "remode adapter");
293 for (i
= 1; i
< 4; i
++) {
294 if ((pa
= diva_q_get_next(&pa
->link
))
295 && !pa
->interface
.cleanup_adapter_proc
) {
302 for (i
= 0; ((i
< 4) && a
[i
]); i
++) {
303 list_del(&a
[i
]->link
);
306 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "driver_unload");
308 (*(a
[0]->interface
.cleanup_adapter_proc
)) (a
[0]);
310 for (i
= 0; i
< 4; 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
]);
317 diva_os_free(0, a
[i
]);
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
)
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
;
331 DBG_LOG(("found %d-%s", pI
->CardOrdinal
, CardProperties
[pI
->CardOrdinal
].Name
))
333 if (!(a
= (diva_os_xdi_adapter_t
*) diva_os_malloc(0, sizeof(*a
)))) {
334 DBG_ERR(("A: can't alloc adapter"));
338 memset(a
, 0x00, sizeof(*a
));
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
;
349 Add master adapter first, so slave adapters will receive higher
350 numbers as master adapter
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");
356 if ((*(pI
->init_card
)) (a
)) {
357 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "found_pci_card");
359 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "found_pci_card");
361 DBG_ERR(("A: can't get adapter resources"));
368 /* --------------------------------------------------------------------------
369 Called on driver unload FINIT, finit, Unload
370 -------------------------------------------------------------------------- */
371 void divasa_xdi_driver_unload(void)
373 diva_os_xdi_adapter_t
*a
;
375 while ((a
= get_and_remove_from_queue())) {
376 if (a
->interface
.cleanup_adapter_proc
) {
377 (*(a
->interface
.cleanup_adapter_proc
)) (a
);
380 IoAdapters
[a
->controller
- 1] = NULL
;
381 remove_adapter_proc(a
);
385 diva_os_destroy_spin_lock(&adapter_lock
, "adapter");
389 ** Receive and process command from user mode utility
391 void *diva_xdi_open_adapter(void *os_handle
, const void __user
*src
,
393 divas_xdi_copy_from_user_fn_t cp_fn
)
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
;
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
)))
405 if ((*cp_fn
) (os_handle
, &msg
, src
, sizeof(msg
)) <= 0) {
406 DBG_ERR(("A: A(?) open, write error"))
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
)
416 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "open_adapter");
419 DBG_ERR(("A: A(%d) open, adapter not found", msg
.adapter
))
426 ** Easy cleanup mailbox status
428 void diva_xdi_close_adapter(void *adapter
, void *os_handle
)
430 diva_os_xdi_adapter_t
*a
= (diva_os_xdi_adapter_t
*) adapter
;
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
;
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
)
443 diva_os_xdi_adapter_t
*a
= (diva_os_xdi_adapter_t
*) adapter
;
446 if (a
->xdi_mbox
.status
& DIVA_XDI_MBOX_BUSY
) {
447 DBG_ERR(("A: A(%d) write, mbox busy", a
->controller
))
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
)))
458 if (!(data
= diva_os_malloc(0, length
))) {
459 DBG_ERR(("A: A(%d) write, ENOMEM", a
->controller
))
463 length
= (*cp_fn
) (os_handle
, data
, src
, length
);
465 if ((*(a
->interface
.cmd_proc
))
466 (a
, (diva_xdi_um_cfg_cmd_t
*) data
, length
)) {
470 DBG_ERR(("A: A(%d) write error (%d)", a
->controller
,
474 diva_os_free(0, data
);
480 ** Write answers to user mode utility, if any
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
)
486 diva_os_xdi_adapter_t
*a
= (diva_os_xdi_adapter_t
*) adapter
;
489 if (!(a
->xdi_mbox
.status
& DIVA_XDI_MBOX_BUSY
)) {
490 DBG_ERR(("A: A(%d) rx mbox empty", a
->controller
))
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
))
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
))
506 ret
= (*cp_fn
) (os_handle
, dst
, a
->xdi_mbox
.data
,
507 a
->xdi_mbox
.data_length
);
509 diva_os_free(0, a
->xdi_mbox
.data
);
510 a
->xdi_mbox
.data
= NULL
;
511 a
->xdi_mbox
.status
&= ~DIVA_XDI_MBOX_BUSY
;
518 irqreturn_t
diva_os_irq_wrapper(int irq
, void *context
, struct pt_regs
*regs
)
520 diva_os_xdi_adapter_t
*a
= (diva_os_xdi_adapter_t
*) context
;
521 diva_xdi_clear_interrupts_proc_t clear_int_proc
;
523 if (!a
|| !a
->xdi_adapter
.diva_isr_handler
) {
527 if ((clear_int_proc
= a
->clear_interrupts_proc
)) {
528 (*clear_int_proc
) (a
);
529 a
->clear_interrupts_proc
= NULL
;
533 (*(a
->xdi_adapter
.diva_isr_handler
)) (&a
->xdi_adapter
);
537 static void diva_init_request_array(void)
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
;
573 void diva_xdi_display_adapter_features(int card
)
576 if (!card
|| ((card
- 1) >= MAX_ADAPTER
) || !IoAdapters
[card
- 1]) {
580 features
= IoAdapters
[card
]->Properties
.Features
;
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"))
609 void diva_add_slave_adapter(diva_os_xdi_adapter_t
* a
)
611 diva_os_spin_lock_magic_t old_irql
;
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");
618 int diva_card_read_xlog(diva_os_xdi_adapter_t
* a
)
620 diva_get_xlog_t
*req
;
623 if (!a
->xdi_adapter
.Initialized
|| !a
->xdi_adapter
.DIRequest
) {
626 if (!(data
= diva_os_malloc(0, sizeof(struct mi_pc_maint
)))) {
629 memset(data
, 0x00, sizeof(struct mi_pc_maint
));
631 if (!(req
= diva_os_malloc(0, sizeof(*req
)))) {
632 diva_os_free(0, data
);
635 req
->command
= 0x0400;
639 (*(a
->xdi_adapter
.DIRequest
)) (&a
->xdi_adapter
, (ENTITY
*) req
);
641 if (!req
->rc
|| req
->req
) {
642 diva_os_free(0, data
);
643 diva_os_free(0, req
);
647 memcpy(data
, &req
->req
, sizeof(struct mi_pc_maint
));
649 diva_os_free(0, req
);
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
;
658 void xdiFreeFile(void *handle
)