Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
um_idi.c
Go to the documentation of this file.
1 /* $Id: um_idi.c,v 1.14 2004/03/21 17:54:37 armin Exp $ */
2 
3 #include "platform.h"
4 #include "di_defs.h"
5 #include "pc.h"
6 #include "dqueue.h"
7 #include "adapter.h"
8 #include "entity.h"
9 #include "um_xdi.h"
10 #include "um_idi.h"
11 #include "debuglib.h"
12 #include "divasync.h"
13 
14 #define DIVAS_MAX_XDI_ADAPTERS 64
15 
16 /* --------------------------------------------------------------------------
17  IMPORTS
18  -------------------------------------------------------------------------- */
19 extern void diva_os_wakeup_read(void *os_context);
20 extern void diva_os_wakeup_close(void *os_context);
21 /* --------------------------------------------------------------------------
22  LOCALS
23  -------------------------------------------------------------------------- */
24 static LIST_HEAD(adapter_q);
25 static diva_os_spin_lock_t adapter_lock;
26 
27 static diva_um_idi_adapter_t *diva_um_idi_find_adapter(dword nr);
28 static void cleanup_adapter(diva_um_idi_adapter_t *a);
29 static void cleanup_entity(divas_um_idi_entity_t *e);
30 static int diva_user_mode_idi_adapter_features(diva_um_idi_adapter_t *a,
32  *features);
33 static int process_idi_request(divas_um_idi_entity_t *e,
34  const diva_um_idi_req_hdr_t *req);
35 static int process_idi_rc(divas_um_idi_entity_t *e, byte rc);
36 static int process_idi_ind(divas_um_idi_entity_t *e, byte ind);
37 static int write_return_code(divas_um_idi_entity_t *e, byte rc);
38 
39 /* --------------------------------------------------------------------------
40  MAIN
41  -------------------------------------------------------------------------- */
43 {
44  diva_os_initialize_spin_lock(&adapter_lock, "adapter");
45  return (0);
46 }
47 
48 /* --------------------------------------------------------------------------
49  Copy adapter features to user supplied buffer
50  -------------------------------------------------------------------------- */
51 static int
52 diva_user_mode_idi_adapter_features(diva_um_idi_adapter_t *a,
54  features)
55 {
56  IDI_SYNC_REQ sync_req;
57 
58  if ((a) && (a->d.request)) {
59  features->type = a->d.type;
60  features->features = a->d.features;
61  features->channels = a->d.channels;
62  memset(features->name, 0, sizeof(features->name));
63 
64  sync_req.GetName.Req = 0;
65  sync_req.GetName.Rc = IDI_SYNC_REQ_GET_NAME;
66  (*(a->d.request)) ((ENTITY *)&sync_req);
67  strlcpy(features->name, sync_req.GetName.name,
68  sizeof(features->name));
69 
70  sync_req.GetSerial.Req = 0;
71  sync_req.GetSerial.Rc = IDI_SYNC_REQ_GET_SERIAL;
72  sync_req.GetSerial.serial = 0;
73  (*(a->d.request))((ENTITY *)&sync_req);
74  features->serial_number = sync_req.GetSerial.serial;
75  }
76 
77  return ((a) ? 0 : -1);
78 }
79 
80 /* --------------------------------------------------------------------------
81  REMOVE ADAPTER
82  -------------------------------------------------------------------------- */
84 {
85  struct list_head *tmp;
87 
88  list_for_each(tmp, &adapter_q) {
90  if (a->adapter_nr == adapter_nr) {
91  list_del(tmp);
92  cleanup_adapter(a);
93  DBG_LOG(("DIDD: del adapter(%d)", a->adapter_nr));
94  diva_os_free(0, a);
95  break;
96  }
97  }
98 }
99 
100 /* --------------------------------------------------------------------------
101  CALLED ON DRIVER EXIT (UNLOAD)
102  -------------------------------------------------------------------------- */
104 {
105  struct list_head *tmp, *safe;
107 
108  list_for_each_safe(tmp, safe, &adapter_q) {
110  list_del(tmp);
111  cleanup_adapter(a);
112  DBG_LOG(("DIDD: del adapter(%d)", a->adapter_nr));
113  diva_os_free(0, a);
114  }
115  diva_os_destroy_spin_lock(&adapter_lock, "adapter");
116 }
117 
118 /* -------------------------------------------------------------------------
119  CREATE AND INIT IDI ADAPTER
120  ------------------------------------------------------------------------- */
121 int diva_user_mode_idi_create_adapter(const DESCRIPTOR *d, int adapter_nr)
122 {
123  diva_os_spin_lock_magic_t old_irql;
125  (diva_um_idi_adapter_t *) diva_os_malloc(0,
126  sizeof
128 
129  if (!a) {
130  return (-1);
131  }
132  memset(a, 0x00, sizeof(*a));
133  INIT_LIST_HEAD(&a->entity_q);
134 
135  a->d = *d;
136  a->adapter_nr = adapter_nr;
137 
138  DBG_LOG(("DIDD_ADD A(%d), type:%02x, features:%04x, channels:%d",
139  adapter_nr, a->d.type, a->d.features, a->d.channels));
140 
141  diva_os_enter_spin_lock(&adapter_lock, &old_irql, "create_adapter");
142  list_add_tail(&a->link, &adapter_q);
143  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "create_adapter");
144  return (0);
145 }
146 
147 /* ------------------------------------------------------------------------
148  Find adapter by Adapter number
149  ------------------------------------------------------------------------ */
150 static diva_um_idi_adapter_t *diva_um_idi_find_adapter(dword nr)
151 {
153  struct list_head *tmp;
154 
155  list_for_each(tmp, &adapter_q) {
157  DBG_TRC(("find_adapter: (%d)-(%d)", nr, a->adapter_nr));
158  if (a->adapter_nr == (int)nr)
159  break;
160  a = NULL;
161  }
162  return (a);
163 }
164 
165 /* ------------------------------------------------------------------------
166  Cleanup this adapter and cleanup/delete all entities assigned
167  to this adapter
168  ------------------------------------------------------------------------ */
169 static void cleanup_adapter(diva_um_idi_adapter_t *a)
170 {
171  struct list_head *tmp, *safe;
173 
174  list_for_each_safe(tmp, safe, &a->entity_q) {
176  list_del(tmp);
177  cleanup_entity(e);
178  if (e->os_context) {
181  }
182  }
183  memset(&a->d, 0x00, sizeof(DESCRIPTOR));
184 }
185 
186 /* ------------------------------------------------------------------------
187  Cleanup, but NOT delete this entity
188  ------------------------------------------------------------------------ */
189 static void cleanup_entity(divas_um_idi_entity_t *e)
190 {
191  e->os_ref = NULL;
192  e->status = 0;
193  e->adapter = NULL;
194  e->e.Id = 0;
195  e->rc_count = 0;
196 
199 
200  diva_data_q_finit(&e->data);
201  diva_data_q_finit(&e->rc);
202 }
203 
204 
205 /* ------------------------------------------------------------------------
206  Create ENTITY, link it to the adapter and remove pointer to entity
207  ------------------------------------------------------------------------ */
208 void *divas_um_idi_create_entity(dword adapter_nr, void *file)
209 {
212  diva_os_spin_lock_magic_t old_irql;
213 
214  if ((e = (divas_um_idi_entity_t *) diva_os_malloc(0, sizeof(*e)))) {
215  memset(e, 0x00, sizeof(*e));
216  if (!
217  (e->os_context =
218  diva_os_malloc(0, diva_os_get_context_size()))) {
219  DBG_LOG(("E(%08x) no memory for os context", e));
220  diva_os_free(0, e);
221  return NULL;
222  }
224 
225  if ((diva_data_q_init(&e->data, 2048 + 512, 16))) {
226  diva_os_free(0, e->os_context);
227  diva_os_free(0, e);
228  return NULL;
229  }
230  if ((diva_data_q_init(&e->rc, sizeof(diva_um_idi_ind_hdr_t), 2))) {
231  diva_data_q_finit(&e->data);
232  diva_os_free(0, e->os_context);
233  diva_os_free(0, e);
234  return NULL;
235  }
236 
237  diva_os_enter_spin_lock(&adapter_lock, &old_irql, "create_entity");
238  /*
239  Look for Adapter requested
240  */
241  if (!(a = diva_um_idi_find_adapter(adapter_nr))) {
242  /*
243  No adapter was found, or this adapter was removed
244  */
245  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "create_entity");
246 
247  DBG_LOG(("A: no adapter(%ld)", adapter_nr));
248 
249  cleanup_entity(e);
250  diva_os_free(0, e->os_context);
251  diva_os_free(0, e);
252 
253  return NULL;
254  }
255 
256  e->os_ref = file; /* link to os handle */
257  e->adapter = a; /* link to adapter */
258 
259  list_add_tail(&e->link, &a->entity_q); /* link from adapter */
260 
261  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "create_entity");
262 
263  DBG_LOG(("A(%ld), create E(%08x)", adapter_nr, e));
264  }
265 
266  return (e);
267 }
268 
269 /* ------------------------------------------------------------------------
270  Unlink entity and free memory
271  ------------------------------------------------------------------------ */
272 int divas_um_idi_delete_entity(int adapter_nr, void *entity)
273 {
276  diva_os_spin_lock_magic_t old_irql;
277 
278  if (!(e = (divas_um_idi_entity_t *) entity))
279  return (-1);
280 
281  diva_os_enter_spin_lock(&adapter_lock, &old_irql, "delete_entity");
282  if ((a = e->adapter)) {
283  list_del(&e->link);
284  }
285  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "delete_entity");
286 
287  diva_um_idi_stop_wdog(entity);
288  cleanup_entity(e);
289  diva_os_free(0, e->os_context);
290  memset(e, 0x00, sizeof(*e));
291  diva_os_free(0, e);
292 
293  DBG_LOG(("A(%d) remove E:%08x", adapter_nr, e));
294 
295  return (0);
296 }
297 
298 /* --------------------------------------------------------------------------
299  Called by application to read data from IDI
300  -------------------------------------------------------------------------- */
301 int diva_um_idi_read(void *entity,
302  void *os_handle,
303  void *dst,
304  int max_length, divas_um_idi_copy_to_user_fn_t cp_fn)
305 {
308  const void *data;
309  int length, ret = 0;
311  diva_os_spin_lock_magic_t old_irql;
312 
313  diva_os_enter_spin_lock(&adapter_lock, &old_irql, "read");
314 
315  e = (divas_um_idi_entity_t *) entity;
316  if (!e || (!(a = e->adapter)) ||
318  (e->status & DIVA_UM_IDI_REMOVED) ||
320  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "read");
321  DBG_ERR(("E(%08x) read failed - adapter removed", e))
322  return (-1);
323  }
324 
325  DBG_TRC(("A(%d) E(%08x) read(%d)", a->adapter_nr, e, max_length));
326 
327  /*
328  Try to read return code first
329  */
330  data = diva_data_q_get_segment4read(&e->rc);
331  q = &e->rc;
332 
333  /*
334  No return codes available, read indications now
335  */
336  if (!data) {
337  if (!(e->status & DIVA_UM_IDI_RC_PENDING)) {
338  DBG_TRC(("A(%d) E(%08x) read data", a->adapter_nr, e));
340  q = &e->data;
341  }
342  } else {
344  DBG_TRC(("A(%d) E(%08x) read rc", a->adapter_nr, e));
345  }
346 
347  if (data) {
348  if ((length = diva_data_q_get_segment_length(q)) >
349  max_length) {
350  /*
351  Not enough space to read message
352  */
353  DBG_ERR(("A: A(%d) E(%08x) read small buffer",
354  a->adapter_nr, e, ret));
355  diva_os_leave_spin_lock(&adapter_lock, &old_irql,
356  "read");
357  return (-2);
358  }
359  /*
360  Copy it to user, this function does access ONLY locked an verified
361  memory, also we can access it witch spin lock held
362  */
363 
364  if ((ret = (*cp_fn) (os_handle, dst, data, length)) >= 0) {
365  /*
366  Acknowledge only if read was successful
367  */
369  }
370  }
371 
372 
373  DBG_TRC(("A(%d) E(%08x) read=%d", a->adapter_nr, e, ret));
374 
375  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "read");
376 
377  return (ret);
378 }
379 
380 
381 int diva_um_idi_write(void *entity,
382  void *os_handle,
383  const void *src,
385 {
389  void *data;
390  int ret = 0;
391  diva_os_spin_lock_magic_t old_irql;
392 
393  diva_os_enter_spin_lock(&adapter_lock, &old_irql, "write");
394 
395  e = (divas_um_idi_entity_t *) entity;
396  if (!e || (!(a = e->adapter)) ||
398  (e->status & DIVA_UM_IDI_REMOVED) ||
400  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
401  DBG_ERR(("E(%08x) write failed - adapter removed", e))
402  return (-1);
403  }
404 
405  DBG_TRC(("A(%d) E(%08x) write(%d)", a->adapter_nr, e, length));
406 
407  if ((length < sizeof(*req)) || (length > sizeof(e->buffer))) {
408  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
409  return (-2);
410  }
411 
412  if (e->status & DIVA_UM_IDI_RC_PENDING) {
413  DBG_ERR(("A: A(%d) E(%08x) rc pending", a->adapter_nr, e));
414  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
415  return (-1); /* should wait for RC code first */
416  }
417 
418  /*
419  Copy function does access only locked verified memory,
420  also it can be called with spin lock held
421  */
422  if ((ret = (*cp_fn) (os_handle, e->buffer, src, length)) < 0) {
423  DBG_TRC(("A: A(%d) E(%08x) write error=%d", a->adapter_nr,
424  e, ret));
425  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
426  return (ret);
427  }
428 
429  req = (diva_um_idi_req_hdr_t *)&e->buffer[0];
430 
431  switch (req->type) {
433  DBG_LOG(("A(%d) get_features", a->adapter_nr));
434  if (!(data =
436  DBG_ERR(("A(%d) get_features, no free buffer",
437  a->adapter_nr));
438  diva_os_leave_spin_lock(&adapter_lock,
439  &old_irql,
440  "write");
441  return (0);
442  }
443  diva_user_mode_idi_adapter_features(a, &(((diva_um_idi_ind_hdr_t
444  *) data)->hdr.features));
445  ((diva_um_idi_ind_hdr_t *) data)->type =
447  ((diva_um_idi_ind_hdr_t *) data)->data_length = 0;
449  sizeof(diva_um_idi_ind_hdr_t));
450 
451  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
452 
454  }
455  break;
456 
457  case DIVA_UM_IDI_REQ:
458  case DIVA_UM_IDI_REQ_MAN:
459  case DIVA_UM_IDI_REQ_SIG:
460  case DIVA_UM_IDI_REQ_NET:
461  DBG_TRC(("A(%d) REQ(%02d)-(%02d)-(%08x)", a->adapter_nr,
462  req->Req, req->ReqCh,
464  switch (process_idi_request(e, req)) {
465  case -1:
466  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
467  return (-1);
468  case -2:
469  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
471  break;
472  default:
473  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
474  break;
475  }
476  break;
477 
478  default:
479  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write");
480  return (-1);
481  }
482 
483  DBG_TRC(("A(%d) E(%08x) write=%d", a->adapter_nr, e, ret));
484 
485  return (ret);
486 }
487 
488 /* --------------------------------------------------------------------------
489  CALLBACK FROM XDI
490  -------------------------------------------------------------------------- */
491 static void diva_um_idi_xdi_callback(ENTITY *entity)
492 {
495  e);
496  diva_os_spin_lock_magic_t old_irql;
497  int call_wakeup = 0;
498 
499  diva_os_enter_spin_lock(&adapter_lock, &old_irql, "xdi_callback");
500 
501  if (e->e.complete == 255) {
502  if (!(e->status & DIVA_UM_IDI_REMOVE_PENDING)) {
504  }
505  if ((call_wakeup = process_idi_rc(e, e->e.Rc))) {
506  if (e->rc_count) {
507  e->rc_count--;
508  }
509  }
510  e->e.Rc = 0;
511  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "xdi_callback");
512 
513  if (call_wakeup) {
516  }
517  } else {
519  e->e.RNum = 0;
520  e->e.RNR = 2;
521  } else {
522  call_wakeup = process_idi_ind(e, e->e.Ind);
523  }
524  e->e.Ind = 0;
525  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "xdi_callback");
526  if (call_wakeup) {
528  }
529  }
530 }
531 
532 static int process_idi_request(divas_um_idi_entity_t *e,
533  const diva_um_idi_req_hdr_t *req)
534 {
535  int assign = 0;
536  byte Req = (byte) req->Req;
538 
539  if (!e->e.Id || !e->e.callback) { /* not assigned */
540  if (Req != ASSIGN) {
541  DBG_ERR(("A: A(%d) E(%08x) not assigned",
542  e->adapter->adapter_nr, e));
543  return (-1); /* NOT ASSIGNED */
544  } else {
545  switch (type) {
547  e->e.Id = MAN_ID;
548  DBG_TRC(("A(%d) E(%08x) assign MAN",
549  e->adapter->adapter_nr, e));
550  break;
551 
553  e->e.Id = DSIG_ID;
554  DBG_TRC(("A(%d) E(%08x) assign SIG",
555  e->adapter->adapter_nr, e));
556  break;
557 
559  e->e.Id = NL_ID;
560  DBG_TRC(("A(%d) E(%08x) assign NET",
561  e->adapter->adapter_nr, e));
562  break;
563 
564  default:
565  DBG_ERR(("A: A(%d) E(%08x) unknown type=%08x",
566  e->adapter->adapter_nr, e,
567  type));
568  return (-1);
569  }
570  }
571  e->e.XNum = 1;
572  e->e.RNum = 1;
573  e->e.callback = diva_um_idi_xdi_callback;
574  e->e.X = &e->XData;
575  e->e.R = &e->RData;
576  assign = 1;
577  }
579  e->e.Req = Req;
580  e->e.ReqCh = (byte) req->ReqCh;
581  e->e.X->PLength = (word) req->data_length;
582  e->e.X->P = (byte *)&req[1]; /* Our buffer is safe */
583 
584  DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))",
585  e->adapter->adapter_nr, e, e->e.Id, e->e.Req,
586  e->e.ReqCh, e->e.X->PLength));
587 
588  e->rc_count++;
589 
590  if (e->adapter && e->adapter->d.request) {
592  (*(e->adapter->d.request)) (&e->e);
593  }
594 
595  if (assign) {
596  if (e->e.Rc == OUT_OF_RESOURCES) {
597  /*
598  XDI has no entities more, call was not forwarded to the card,
599  no callback will be scheduled
600  */
601  DBG_ERR(("A: A(%d) E(%08x) XDI out of entities",
602  e->adapter->adapter_nr, e));
603 
604  e->e.Id = 0;
605  e->e.ReqCh = 0;
606  e->e.RcCh = 0;
607  e->e.Ind = 0;
608  e->e.IndCh = 0;
609  e->e.XNum = 0;
610  e->e.RNum = 0;
611  e->e.callback = NULL;
612  e->e.X = NULL;
613  e->e.R = NULL;
614  write_return_code(e, ASSIGN_RC | OUT_OF_RESOURCES);
615  return (-2);
616  } else {
618  }
619  }
620 
621  return (0);
622 }
623 
624 static int process_idi_rc(divas_um_idi_entity_t *e, byte rc)
625 {
626  DBG_TRC(("A(%d) E(%08x) rc(%02x-%02x-%02x)",
627  e->adapter->adapter_nr, e, e->e.Id, rc, e->e.RcCh));
628 
631  if (rc != ASSIGN_OK) {
632  DBG_ERR(("A: A(%d) E(%08x) ASSIGN failed",
633  e->adapter->adapter_nr, e));
634  e->e.callback = NULL;
635  e->e.Id = 0;
636  e->e.Req = 0;
637  e->e.ReqCh = 0;
638  e->e.Rc = 0;
639  e->e.RcCh = 0;
640  e->e.Ind = 0;
641  e->e.IndCh = 0;
642  e->e.X = NULL;
643  e->e.R = NULL;
644  e->e.XNum = 0;
645  e->e.RNum = 0;
646  }
647  }
648  if ((e->e.Req == REMOVE) && e->e.Id && (rc == 0xff)) {
649  DBG_ERR(("A: A(%d) E(%08x) discard OK in REMOVE",
650  e->adapter->adapter_nr, e));
651  return (0); /* let us do it in the driver */
652  }
653  if ((e->e.Req == REMOVE) && (!e->e.Id)) { /* REMOVE COMPLETE */
654  e->e.callback = NULL;
655  e->e.Id = 0;
656  e->e.Req = 0;
657  e->e.ReqCh = 0;
658  e->e.Rc = 0;
659  e->e.RcCh = 0;
660  e->e.Ind = 0;
661  e->e.IndCh = 0;
662  e->e.X = NULL;
663  e->e.R = NULL;
664  e->e.XNum = 0;
665  e->e.RNum = 0;
666  e->rc_count = 0;
667  }
668  if ((e->e.Req == REMOVE) && (rc != 0xff)) { /* REMOVE FAILED */
669  DBG_ERR(("A: A(%d) E(%08x) REMOVE FAILED",
670  e->adapter->adapter_nr, e));
671  }
672  write_return_code(e, rc);
673 
674  return (1);
675 }
676 
677 static int process_idi_ind(divas_um_idi_entity_t *e, byte ind)
678 {
679  int do_wakeup = 0;
680 
681  if (e->e.complete != 0x02) {
682  diva_um_idi_ind_hdr_t *pind =
685  if (pind) {
686  e->e.RNum = 1;
687  e->e.R->P = (byte *)&pind[1];
688  e->e.R->PLength =
690  sizeof(*pind));
691  DBG_TRC(("A(%d) E(%08x) ind_1(%02x-%02x-%02x)-[%d-%d]",
692  e->adapter->adapter_nr, e, e->e.Id, ind,
693  e->e.IndCh, e->e.RLength,
694  e->e.R->PLength));
695 
696  } else {
697  DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-RNR",
698  e->adapter->adapter_nr, e, e->e.Id, ind,
699  e->e.IndCh));
700  e->e.RNum = 0;
701  e->e.RNR = 1;
702  do_wakeup = 1;
703  }
704  } else {
705  diva_um_idi_ind_hdr_t *pind =
706  (diva_um_idi_ind_hdr_t *) (e->e.R->P);
707 
708  DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-[%d]",
709  e->adapter->adapter_nr, e, e->e.Id, ind,
710  e->e.IndCh, e->e.R->PLength));
711 
712  pind--;
713  pind->type = DIVA_UM_IDI_IND;
714  pind->hdr.ind.Ind = ind;
715  pind->hdr.ind.IndCh = e->e.IndCh;
716  pind->data_length = e->e.R->PLength;
718  (int) (sizeof(*pind) +
719  e->e.R->PLength));
720  do_wakeup = 1;
721  }
722 
723  if ((e->status & DIVA_UM_IDI_RC_PENDING) && !e->rc.count) {
724  do_wakeup = 0;
725  }
726 
727  return (do_wakeup);
728 }
729 
730 /* --------------------------------------------------------------------------
731  Write return code to the return code queue of entity
732  -------------------------------------------------------------------------- */
733 static int write_return_code(divas_um_idi_entity_t *e, byte rc)
734 {
736 
737  if (!(prc =
739  {
740  DBG_ERR(("A: A(%d) E(%08x) rc(%02x) lost",
741  e->adapter->adapter_nr, e, rc));
743  return (-1);
744  }
745 
746  prc->type = DIVA_UM_IDI_IND_RC;
747  prc->hdr.rc.Rc = rc;
748  prc->hdr.rc.RcCh = e->e.RcCh;
749  prc->data_length = 0;
750  diva_data_q_ack_segment4write(&e->rc, sizeof(*prc));
751 
752  return (0);
753 }
754 
755 /* --------------------------------------------------------------------------
756  Return amount of entries that can be bead from this entity or
757  -1 if adapter was removed
758  -------------------------------------------------------------------------- */
759 int diva_user_mode_idi_ind_ready(void *entity, void *os_handle)
760 {
763  diva_os_spin_lock_magic_t old_irql;
764  int ret;
765 
766  if (!entity)
767  return (-1);
768  diva_os_enter_spin_lock(&adapter_lock, &old_irql, "ind_ready");
769  e = (divas_um_idi_entity_t *) entity;
770  a = e->adapter;
771 
772  if ((!a) || (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) {
773  /*
774  Adapter was unloaded
775  */
776  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready");
777  return (-1); /* adapter was removed */
778  }
779  if (e->status & DIVA_UM_IDI_REMOVED) {
780  /*
781  entity was removed as result of adapter removal
782  user should assign this entity again
783  */
784  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready");
785  return (-1);
786  }
787 
788  ret = e->rc.count + e->data.count;
789 
790  if ((e->status & DIVA_UM_IDI_RC_PENDING) && !e->rc.count) {
791  ret = 0;
792  }
793 
794  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready");
795 
796  return (ret);
797 }
798 
799 void *diva_um_id_get_os_context(void *entity)
800 {
801  return (((divas_um_idi_entity_t *) entity)->os_context);
802 }
803 
805 {
808  int ret;
809  diva_os_spin_lock_magic_t old_irql;
810 
811  diva_os_enter_spin_lock(&adapter_lock, &old_irql, "assigned?");
812 
813 
814  e = (divas_um_idi_entity_t *) entity;
815  if (!e || (!(a = e->adapter)) ||
816  (e->status & DIVA_UM_IDI_REMOVED) ||
818  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "assigned?");
819  return (0);
820  }
821 
823 
824  ret = (e->e.Id || e->rc_count
826 
827  DBG_TRC(("Id:%02x, rc_count:%d, status:%08x", e->e.Id, e->rc_count,
828  e->status))
829 
830  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "assigned?");
831 
832  return (ret);
833 }
834 
836 {
839  diva_os_spin_lock_magic_t old_irql;
840 
841  diva_os_enter_spin_lock(&adapter_lock, &old_irql, "start_remove");
842 
843  e = (divas_um_idi_entity_t *) entity;
844  if (!e || (!(a = e->adapter)) ||
845  (e->status & DIVA_UM_IDI_REMOVED) ||
847  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
848  return (0);
849  }
850 
851  if (e->rc_count) {
852  /*
853  Entity BUSY
854  */
855  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
856  return (1);
857  }
858 
859  if (!e->e.Id) {
860  /*
861  Remove request was already pending, and arrived now
862  */
863  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
864  return (0); /* REMOVE was pending */
865  }
866 
867  /*
868  Now send remove request
869  */
870  e->e.Req = REMOVE;
871  e->e.ReqCh = 0;
872 
873  e->rc_count++;
874 
875  DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))",
876  e->adapter->adapter_nr, e, e->e.Id, e->e.Req,
877  e->e.ReqCh, e->e.X->PLength));
878 
879  if (a->d.request)
880  (*(a->d.request)) (&e->e);
881 
882  diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove");
883 
884  return (0);
885 }