1 // SPDX-License-Identifier: GPL-2.0
2 /* $Id: um_idi.c,v 1.14 2004/03/21 17:54:37 armin Exp $ */
15 #define DIVAS_MAX_XDI_ADAPTERS 64
17 /* --------------------------------------------------------------------------
19 -------------------------------------------------------------------------- */
20 extern void diva_os_wakeup_read(void *os_context
);
21 extern void diva_os_wakeup_close(void *os_context
);
22 /* --------------------------------------------------------------------------
24 -------------------------------------------------------------------------- */
25 static LIST_HEAD(adapter_q
);
26 static diva_os_spin_lock_t adapter_lock
;
28 static diva_um_idi_adapter_t
*diva_um_idi_find_adapter(dword nr
);
29 static void cleanup_adapter(diva_um_idi_adapter_t
*a
);
30 static void cleanup_entity(divas_um_idi_entity_t
*e
);
31 static int diva_user_mode_idi_adapter_features(diva_um_idi_adapter_t
*a
,
32 diva_um_idi_adapter_features_t
34 static int process_idi_request(divas_um_idi_entity_t
*e
,
35 const diva_um_idi_req_hdr_t
*req
);
36 static int process_idi_rc(divas_um_idi_entity_t
*e
, byte rc
);
37 static int process_idi_ind(divas_um_idi_entity_t
*e
, byte ind
);
38 static int write_return_code(divas_um_idi_entity_t
*e
, byte rc
);
40 /* --------------------------------------------------------------------------
42 -------------------------------------------------------------------------- */
43 int diva_user_mode_idi_init(void)
45 diva_os_initialize_spin_lock(&adapter_lock
, "adapter");
49 /* --------------------------------------------------------------------------
50 Copy adapter features to user supplied buffer
51 -------------------------------------------------------------------------- */
53 diva_user_mode_idi_adapter_features(diva_um_idi_adapter_t
*a
,
54 diva_um_idi_adapter_features_t
*
57 IDI_SYNC_REQ sync_req
;
59 if ((a
) && (a
->d
.request
)) {
60 features
->type
= a
->d
.type
;
61 features
->features
= a
->d
.features
;
62 features
->channels
= a
->d
.channels
;
63 memset(features
->name
, 0, sizeof(features
->name
));
65 sync_req
.GetName
.Req
= 0;
66 sync_req
.GetName
.Rc
= IDI_SYNC_REQ_GET_NAME
;
67 (*(a
->d
.request
)) ((ENTITY
*)&sync_req
);
68 strlcpy(features
->name
, sync_req
.GetName
.name
,
69 sizeof(features
->name
));
71 sync_req
.GetSerial
.Req
= 0;
72 sync_req
.GetSerial
.Rc
= IDI_SYNC_REQ_GET_SERIAL
;
73 sync_req
.GetSerial
.serial
= 0;
74 (*(a
->d
.request
))((ENTITY
*)&sync_req
);
75 features
->serial_number
= sync_req
.GetSerial
.serial
;
78 return ((a
) ? 0 : -1);
81 /* --------------------------------------------------------------------------
83 -------------------------------------------------------------------------- */
84 void diva_user_mode_idi_remove_adapter(int adapter_nr
)
86 struct list_head
*tmp
;
87 diva_um_idi_adapter_t
*a
;
89 list_for_each(tmp
, &adapter_q
) {
90 a
= list_entry(tmp
, diva_um_idi_adapter_t
, link
);
91 if (a
->adapter_nr
== adapter_nr
) {
94 DBG_LOG(("DIDD: del adapter(%d)", a
->adapter_nr
));
101 /* --------------------------------------------------------------------------
102 CALLED ON DRIVER EXIT (UNLOAD)
103 -------------------------------------------------------------------------- */
104 void diva_user_mode_idi_finit(void)
106 struct list_head
*tmp
, *safe
;
107 diva_um_idi_adapter_t
*a
;
109 list_for_each_safe(tmp
, safe
, &adapter_q
) {
110 a
= list_entry(tmp
, diva_um_idi_adapter_t
, link
);
113 DBG_LOG(("DIDD: del adapter(%d)", a
->adapter_nr
));
116 diva_os_destroy_spin_lock(&adapter_lock
, "adapter");
119 /* -------------------------------------------------------------------------
120 CREATE AND INIT IDI ADAPTER
121 ------------------------------------------------------------------------- */
122 int diva_user_mode_idi_create_adapter(const DESCRIPTOR
*d
, int adapter_nr
)
124 diva_os_spin_lock_magic_t old_irql
;
125 diva_um_idi_adapter_t
*a
=
126 (diva_um_idi_adapter_t
*) diva_os_malloc(0,
128 (diva_um_idi_adapter_t
));
133 memset(a
, 0x00, sizeof(*a
));
134 INIT_LIST_HEAD(&a
->entity_q
);
137 a
->adapter_nr
= adapter_nr
;
139 DBG_LOG(("DIDD_ADD A(%d), type:%02x, features:%04x, channels:%d",
140 adapter_nr
, a
->d
.type
, a
->d
.features
, a
->d
.channels
));
142 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "create_adapter");
143 list_add_tail(&a
->link
, &adapter_q
);
144 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "create_adapter");
148 /* ------------------------------------------------------------------------
149 Find adapter by Adapter number
150 ------------------------------------------------------------------------ */
151 static diva_um_idi_adapter_t
*diva_um_idi_find_adapter(dword nr
)
153 diva_um_idi_adapter_t
*a
= NULL
;
154 struct list_head
*tmp
;
156 list_for_each(tmp
, &adapter_q
) {
157 a
= list_entry(tmp
, diva_um_idi_adapter_t
, link
);
158 DBG_TRC(("find_adapter: (%d)-(%d)", nr
, a
->adapter_nr
));
159 if (a
->adapter_nr
== (int)nr
)
166 /* ------------------------------------------------------------------------
167 Cleanup this adapter and cleanup/delete all entities assigned
169 ------------------------------------------------------------------------ */
170 static void cleanup_adapter(diva_um_idi_adapter_t
*a
)
172 struct list_head
*tmp
, *safe
;
173 divas_um_idi_entity_t
*e
;
175 list_for_each_safe(tmp
, safe
, &a
->entity_q
) {
176 e
= list_entry(tmp
, divas_um_idi_entity_t
, link
);
180 diva_os_wakeup_read(e
->os_context
);
181 diva_os_wakeup_close(e
->os_context
);
184 memset(&a
->d
, 0x00, sizeof(DESCRIPTOR
));
187 /* ------------------------------------------------------------------------
188 Cleanup, but NOT delete this entity
189 ------------------------------------------------------------------------ */
190 static void cleanup_entity(divas_um_idi_entity_t
*e
)
198 e
->status
|= DIVA_UM_IDI_REMOVED
;
199 e
->status
|= DIVA_UM_IDI_REMOVE_PENDING
;
201 diva_data_q_finit(&e
->data
);
202 diva_data_q_finit(&e
->rc
);
206 /* ------------------------------------------------------------------------
207 Create ENTITY, link it to the adapter and remove pointer to entity
208 ------------------------------------------------------------------------ */
209 void *divas_um_idi_create_entity(dword adapter_nr
, void *file
)
211 divas_um_idi_entity_t
*e
;
212 diva_um_idi_adapter_t
*a
;
213 diva_os_spin_lock_magic_t old_irql
;
215 if ((e
= (divas_um_idi_entity_t
*) diva_os_malloc(0, sizeof(*e
)))) {
216 memset(e
, 0x00, sizeof(*e
));
219 diva_os_malloc(0, diva_os_get_context_size()))) {
220 DBG_LOG(("E(%08x) no memory for os context", e
));
224 memset(e
->os_context
, 0x00, diva_os_get_context_size());
226 if ((diva_data_q_init(&e
->data
, 2048 + 512, 16))) {
227 diva_os_free(0, e
->os_context
);
231 if ((diva_data_q_init(&e
->rc
, sizeof(diva_um_idi_ind_hdr_t
), 2))) {
232 diva_data_q_finit(&e
->data
);
233 diva_os_free(0, e
->os_context
);
238 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "create_entity");
240 Look for Adapter requested
242 if (!(a
= diva_um_idi_find_adapter(adapter_nr
))) {
244 No adapter was found, or this adapter was removed
246 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "create_entity");
248 DBG_LOG(("A: no adapter(%ld)", adapter_nr
));
251 diva_os_free(0, e
->os_context
);
257 e
->os_ref
= file
; /* link to os handle */
258 e
->adapter
= a
; /* link to adapter */
260 list_add_tail(&e
->link
, &a
->entity_q
); /* link from adapter */
262 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "create_entity");
264 DBG_LOG(("A(%ld), create E(%08x)", adapter_nr
, e
));
270 /* ------------------------------------------------------------------------
271 Unlink entity and free memory
272 ------------------------------------------------------------------------ */
273 int divas_um_idi_delete_entity(int adapter_nr
, void *entity
)
275 divas_um_idi_entity_t
*e
;
276 diva_um_idi_adapter_t
*a
;
277 diva_os_spin_lock_magic_t old_irql
;
279 if (!(e
= (divas_um_idi_entity_t
*) entity
))
282 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "delete_entity");
283 if ((a
= e
->adapter
)) {
286 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "delete_entity");
288 diva_um_idi_stop_wdog(entity
);
290 diva_os_free(0, e
->os_context
);
291 memset(e
, 0x00, sizeof(*e
));
293 DBG_LOG(("A(%d) remove E:%08x", adapter_nr
, e
));
299 /* --------------------------------------------------------------------------
300 Called by application to read data from IDI
301 -------------------------------------------------------------------------- */
302 int diva_um_idi_read(void *entity
,
305 int max_length
, divas_um_idi_copy_to_user_fn_t cp_fn
)
307 divas_um_idi_entity_t
*e
;
308 diva_um_idi_adapter_t
*a
;
311 diva_um_idi_data_queue_t
*q
;
312 diva_os_spin_lock_magic_t old_irql
;
314 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "read");
316 e
= (divas_um_idi_entity_t
*) entity
;
317 if (!e
|| (!(a
= e
->adapter
)) ||
318 (e
->status
& DIVA_UM_IDI_REMOVE_PENDING
) ||
319 (e
->status
& DIVA_UM_IDI_REMOVED
) ||
320 (a
->status
& DIVA_UM_IDI_ADAPTER_REMOVED
)) {
321 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "read");
322 DBG_ERR(("E(%08x) read failed - adapter removed", e
))
326 DBG_TRC(("A(%d) E(%08x) read(%d)", a
->adapter_nr
, e
, max_length
));
329 Try to read return code first
331 data
= diva_data_q_get_segment4read(&e
->rc
);
335 No return codes available, read indications now
338 if (!(e
->status
& DIVA_UM_IDI_RC_PENDING
)) {
339 DBG_TRC(("A(%d) E(%08x) read data", a
->adapter_nr
, e
));
340 data
= diva_data_q_get_segment4read(&e
->data
);
344 e
->status
&= ~DIVA_UM_IDI_RC_PENDING
;
345 DBG_TRC(("A(%d) E(%08x) read rc", a
->adapter_nr
, e
));
349 if ((length
= diva_data_q_get_segment_length(q
)) >
352 Not enough space to read message
354 DBG_ERR(("A: A(%d) E(%08x) read small buffer",
355 a
->adapter_nr
, e
, ret
));
356 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
,
361 Copy it to user, this function does access ONLY locked an verified
362 memory, also we can access it witch spin lock held
365 if ((ret
= (*cp_fn
) (os_handle
, dst
, data
, length
)) >= 0) {
367 Acknowledge only if read was successful
369 diva_data_q_ack_segment4read(q
);
374 DBG_TRC(("A(%d) E(%08x) read=%d", a
->adapter_nr
, e
, ret
));
376 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "read");
382 int diva_um_idi_write(void *entity
,
385 int length
, divas_um_idi_copy_from_user_fn_t cp_fn
)
387 divas_um_idi_entity_t
*e
;
388 diva_um_idi_adapter_t
*a
;
389 diva_um_idi_req_hdr_t
*req
;
392 diva_os_spin_lock_magic_t old_irql
;
394 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "write");
396 e
= (divas_um_idi_entity_t
*) entity
;
397 if (!e
|| (!(a
= e
->adapter
)) ||
398 (e
->status
& DIVA_UM_IDI_REMOVE_PENDING
) ||
399 (e
->status
& DIVA_UM_IDI_REMOVED
) ||
400 (a
->status
& DIVA_UM_IDI_ADAPTER_REMOVED
)) {
401 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "write");
402 DBG_ERR(("E(%08x) write failed - adapter removed", e
))
406 DBG_TRC(("A(%d) E(%08x) write(%d)", a
->adapter_nr
, e
, length
));
408 if ((length
< sizeof(*req
)) || (length
> sizeof(e
->buffer
))) {
409 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "write");
413 if (e
->status
& DIVA_UM_IDI_RC_PENDING
) {
414 DBG_ERR(("A: A(%d) E(%08x) rc pending", a
->adapter_nr
, e
));
415 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "write");
416 return (-1); /* should wait for RC code first */
420 Copy function does access only locked verified memory,
421 also it can be called with spin lock held
423 if ((ret
= (*cp_fn
) (os_handle
, e
->buffer
, src
, length
)) < 0) {
424 DBG_TRC(("A: A(%d) E(%08x) write error=%d", a
->adapter_nr
,
426 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "write");
430 req
= (diva_um_idi_req_hdr_t
*)&e
->buffer
[0];
433 case DIVA_UM_IDI_GET_FEATURES
:{
434 DBG_LOG(("A(%d) get_features", a
->adapter_nr
));
436 diva_data_q_get_segment4write(&e
->data
))) {
437 DBG_ERR(("A(%d) get_features, no free buffer",
439 diva_os_leave_spin_lock(&adapter_lock
,
444 diva_user_mode_idi_adapter_features(a
, &(((diva_um_idi_ind_hdr_t
445 *) data
)->hdr
.features
));
446 ((diva_um_idi_ind_hdr_t
*) data
)->type
=
447 DIVA_UM_IDI_IND_FEATURES
;
448 ((diva_um_idi_ind_hdr_t
*) data
)->data_length
= 0;
449 diva_data_q_ack_segment4write(&e
->data
,
450 sizeof(diva_um_idi_ind_hdr_t
));
452 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "write");
454 diva_os_wakeup_read(e
->os_context
);
458 case DIVA_UM_IDI_REQ
:
459 case DIVA_UM_IDI_REQ_MAN
:
460 case DIVA_UM_IDI_REQ_SIG
:
461 case DIVA_UM_IDI_REQ_NET
:
462 DBG_TRC(("A(%d) REQ(%02d)-(%02d)-(%08x)", a
->adapter_nr
,
463 req
->Req
, req
->ReqCh
,
464 req
->type
& DIVA_UM_IDI_REQ_TYPE_MASK
));
465 switch (process_idi_request(e
, req
)) {
467 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "write");
470 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "write");
471 diva_os_wakeup_read(e
->os_context
);
474 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "write");
480 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "write");
484 DBG_TRC(("A(%d) E(%08x) write=%d", a
->adapter_nr
, e
, ret
));
489 /* --------------------------------------------------------------------------
491 -------------------------------------------------------------------------- */
492 static void diva_um_idi_xdi_callback(ENTITY
*entity
)
494 divas_um_idi_entity_t
*e
= DIVAS_CONTAINING_RECORD(entity
,
495 divas_um_idi_entity_t
,
497 diva_os_spin_lock_magic_t old_irql
;
500 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "xdi_callback");
502 if (e
->e
.complete
== 255) {
503 if (!(e
->status
& DIVA_UM_IDI_REMOVE_PENDING
)) {
504 diva_um_idi_stop_wdog(e
);
506 if ((call_wakeup
= process_idi_rc(e
, e
->e
.Rc
))) {
512 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "xdi_callback");
515 diva_os_wakeup_read(e
->os_context
);
516 diva_os_wakeup_close(e
->os_context
);
519 if (e
->status
& DIVA_UM_IDI_REMOVE_PENDING
) {
523 call_wakeup
= process_idi_ind(e
, e
->e
.Ind
);
526 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "xdi_callback");
528 diva_os_wakeup_read(e
->os_context
);
533 static int process_idi_request(divas_um_idi_entity_t
*e
,
534 const diva_um_idi_req_hdr_t
*req
)
537 byte Req
= (byte
) req
->Req
;
538 dword type
= req
->type
& DIVA_UM_IDI_REQ_TYPE_MASK
;
540 if (!e
->e
.Id
|| !e
->e
.callback
) { /* not assigned */
542 DBG_ERR(("A: A(%d) E(%08x) not assigned",
543 e
->adapter
->adapter_nr
, e
));
544 return (-1); /* NOT ASSIGNED */
547 case DIVA_UM_IDI_REQ_TYPE_MAN
:
549 DBG_TRC(("A(%d) E(%08x) assign MAN",
550 e
->adapter
->adapter_nr
, e
));
553 case DIVA_UM_IDI_REQ_TYPE_SIG
:
555 DBG_TRC(("A(%d) E(%08x) assign SIG",
556 e
->adapter
->adapter_nr
, e
));
559 case DIVA_UM_IDI_REQ_TYPE_NET
:
561 DBG_TRC(("A(%d) E(%08x) assign NET",
562 e
->adapter
->adapter_nr
, e
));
566 DBG_ERR(("A: A(%d) E(%08x) unknown type=%08x",
567 e
->adapter
->adapter_nr
, e
,
574 e
->e
.callback
= diva_um_idi_xdi_callback
;
579 e
->status
|= DIVA_UM_IDI_RC_PENDING
;
581 e
->e
.ReqCh
= (byte
) req
->ReqCh
;
582 e
->e
.X
->PLength
= (word
) req
->data_length
;
583 e
->e
.X
->P
= (byte
*)&req
[1]; /* Our buffer is safe */
585 DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))",
586 e
->adapter
->adapter_nr
, e
, e
->e
.Id
, e
->e
.Req
,
587 e
->e
.ReqCh
, e
->e
.X
->PLength
));
591 if (e
->adapter
&& e
->adapter
->d
.request
) {
592 diva_um_idi_start_wdog(e
);
593 (*(e
->adapter
->d
.request
)) (&e
->e
);
597 if (e
->e
.Rc
== OUT_OF_RESOURCES
) {
599 XDI has no entities more, call was not forwarded to the card,
600 no callback will be scheduled
602 DBG_ERR(("A: A(%d) E(%08x) XDI out of entities",
603 e
->adapter
->adapter_nr
, e
));
612 e
->e
.callback
= NULL
;
615 write_return_code(e
, ASSIGN_RC
| OUT_OF_RESOURCES
);
618 e
->status
|= DIVA_UM_IDI_ASSIGN_PENDING
;
625 static int process_idi_rc(divas_um_idi_entity_t
*e
, byte rc
)
627 DBG_TRC(("A(%d) E(%08x) rc(%02x-%02x-%02x)",
628 e
->adapter
->adapter_nr
, e
, e
->e
.Id
, rc
, e
->e
.RcCh
));
630 if (e
->status
& DIVA_UM_IDI_ASSIGN_PENDING
) {
631 e
->status
&= ~DIVA_UM_IDI_ASSIGN_PENDING
;
632 if (rc
!= ASSIGN_OK
) {
633 DBG_ERR(("A: A(%d) E(%08x) ASSIGN failed",
634 e
->adapter
->adapter_nr
, e
));
635 e
->e
.callback
= NULL
;
649 if ((e
->e
.Req
== REMOVE
) && e
->e
.Id
&& (rc
== 0xff)) {
650 DBG_ERR(("A: A(%d) E(%08x) discard OK in REMOVE",
651 e
->adapter
->adapter_nr
, e
));
652 return (0); /* let us do it in the driver */
654 if ((e
->e
.Req
== REMOVE
) && (!e
->e
.Id
)) { /* REMOVE COMPLETE */
655 e
->e
.callback
= NULL
;
669 if ((e
->e
.Req
== REMOVE
) && (rc
!= 0xff)) { /* REMOVE FAILED */
670 DBG_ERR(("A: A(%d) E(%08x) REMOVE FAILED",
671 e
->adapter
->adapter_nr
, e
));
673 write_return_code(e
, rc
);
678 static int process_idi_ind(divas_um_idi_entity_t
*e
, byte ind
)
682 if (e
->e
.complete
!= 0x02) {
683 diva_um_idi_ind_hdr_t
*pind
=
684 (diva_um_idi_ind_hdr_t
*)
685 diva_data_q_get_segment4write(&e
->data
);
688 e
->e
.R
->P
= (byte
*)&pind
[1];
690 (word
) (diva_data_q_get_max_length(&e
->data
) -
692 DBG_TRC(("A(%d) E(%08x) ind_1(%02x-%02x-%02x)-[%d-%d]",
693 e
->adapter
->adapter_nr
, e
, e
->e
.Id
, ind
,
694 e
->e
.IndCh
, e
->e
.RLength
,
698 DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-RNR",
699 e
->adapter
->adapter_nr
, e
, e
->e
.Id
, ind
,
706 diva_um_idi_ind_hdr_t
*pind
=
707 (diva_um_idi_ind_hdr_t
*) (e
->e
.R
->P
);
709 DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-[%d]",
710 e
->adapter
->adapter_nr
, e
, e
->e
.Id
, ind
,
711 e
->e
.IndCh
, e
->e
.R
->PLength
));
714 pind
->type
= DIVA_UM_IDI_IND
;
715 pind
->hdr
.ind
.Ind
= ind
;
716 pind
->hdr
.ind
.IndCh
= e
->e
.IndCh
;
717 pind
->data_length
= e
->e
.R
->PLength
;
718 diva_data_q_ack_segment4write(&e
->data
,
719 (int) (sizeof(*pind
) +
724 if ((e
->status
& DIVA_UM_IDI_RC_PENDING
) && !e
->rc
.count
) {
731 /* --------------------------------------------------------------------------
732 Write return code to the return code queue of entity
733 -------------------------------------------------------------------------- */
734 static int write_return_code(divas_um_idi_entity_t
*e
, byte rc
)
736 diva_um_idi_ind_hdr_t
*prc
;
739 (diva_um_idi_ind_hdr_t
*) diva_data_q_get_segment4write(&e
->rc
)))
741 DBG_ERR(("A: A(%d) E(%08x) rc(%02x) lost",
742 e
->adapter
->adapter_nr
, e
, rc
));
743 e
->status
&= ~DIVA_UM_IDI_RC_PENDING
;
747 prc
->type
= DIVA_UM_IDI_IND_RC
;
749 prc
->hdr
.rc
.RcCh
= e
->e
.RcCh
;
750 prc
->data_length
= 0;
751 diva_data_q_ack_segment4write(&e
->rc
, sizeof(*prc
));
756 /* --------------------------------------------------------------------------
757 Return amount of entries that can be bead from this entity or
758 -1 if adapter was removed
759 -------------------------------------------------------------------------- */
760 int diva_user_mode_idi_ind_ready(void *entity
, void *os_handle
)
762 divas_um_idi_entity_t
*e
;
763 diva_um_idi_adapter_t
*a
;
764 diva_os_spin_lock_magic_t old_irql
;
769 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "ind_ready");
770 e
= (divas_um_idi_entity_t
*) entity
;
773 if ((!a
) || (a
->status
& DIVA_UM_IDI_ADAPTER_REMOVED
)) {
777 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "ind_ready");
778 return (-1); /* adapter was removed */
780 if (e
->status
& DIVA_UM_IDI_REMOVED
) {
782 entity was removed as result of adapter removal
783 user should assign this entity again
785 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "ind_ready");
789 ret
= e
->rc
.count
+ e
->data
.count
;
791 if ((e
->status
& DIVA_UM_IDI_RC_PENDING
) && !e
->rc
.count
) {
795 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "ind_ready");
800 void *diva_um_id_get_os_context(void *entity
)
802 return (((divas_um_idi_entity_t
*) entity
)->os_context
);
805 int divas_um_idi_entity_assigned(void *entity
)
807 divas_um_idi_entity_t
*e
;
808 diva_um_idi_adapter_t
*a
;
810 diva_os_spin_lock_magic_t old_irql
;
812 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "assigned?");
815 e
= (divas_um_idi_entity_t
*) entity
;
816 if (!e
|| (!(a
= e
->adapter
)) ||
817 (e
->status
& DIVA_UM_IDI_REMOVED
) ||
818 (a
->status
& DIVA_UM_IDI_ADAPTER_REMOVED
)) {
819 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "assigned?");
823 e
->status
|= DIVA_UM_IDI_REMOVE_PENDING
;
825 ret
= (e
->e
.Id
|| e
->rc_count
826 || (e
->status
& DIVA_UM_IDI_ASSIGN_PENDING
));
828 DBG_TRC(("Id:%02x, rc_count:%d, status:%08x", e
->e
.Id
, e
->rc_count
,
831 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "assigned?");
836 int divas_um_idi_entity_start_remove(void *entity
)
838 divas_um_idi_entity_t
*e
;
839 diva_um_idi_adapter_t
*a
;
840 diva_os_spin_lock_magic_t old_irql
;
842 diva_os_enter_spin_lock(&adapter_lock
, &old_irql
, "start_remove");
844 e
= (divas_um_idi_entity_t
*) entity
;
845 if (!e
|| (!(a
= e
->adapter
)) ||
846 (e
->status
& DIVA_UM_IDI_REMOVED
) ||
847 (a
->status
& DIVA_UM_IDI_ADAPTER_REMOVED
)) {
848 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "start_remove");
856 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "start_remove");
862 Remove request was already pending, and arrived now
864 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "start_remove");
865 return (0); /* REMOVE was pending */
869 Now send remove request
876 DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))",
877 e
->adapter
->adapter_nr
, e
, e
->e
.Id
, e
->e
.Req
,
878 e
->e
.ReqCh
, e
->e
.X
->PLength
));
881 (*(a
->d
.request
)) (&e
->e
);
883 diva_os_leave_spin_lock(&adapter_lock
, &old_irql
, "start_remove");