📄 um_idi.c
字号:
*) data)->hdr.features)); ((diva_um_idi_ind_hdr_t *) data)->type = DIVA_UM_IDI_IND_FEATURES; ((diva_um_idi_ind_hdr_t *) data)->data_length = 0; diva_data_q_ack_segment4write(&e->data, sizeof(diva_um_idi_ind_hdr_t)); diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write"); diva_os_wakeup_read(e->os_context); } break; case DIVA_UM_IDI_REQ: case DIVA_UM_IDI_REQ_MAN: case DIVA_UM_IDI_REQ_SIG: case DIVA_UM_IDI_REQ_NET: DBG_TRC(("A(%d) REQ(%02d)-(%02d)-(%08x)", a->adapter_nr, req->Req, req->ReqCh, req->type & DIVA_UM_IDI_REQ_TYPE_MASK)); switch (process_idi_request(e, req)) { case -1: diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write"); return (-1); case -2: diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write"); diva_os_wakeup_read(e->os_context); break; default: diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write"); break; } break; default: diva_os_leave_spin_lock(&adapter_lock, &old_irql, "write"); return (-1); } DBG_TRC(("A(%d) E(%08x) write=%d", a->adapter_nr, e, ret)); return (ret);}/* -------------------------------------------------------------------------- CALLBACK FROM XDI -------------------------------------------------------------------------- */static void diva_um_idi_xdi_callback(ENTITY * entity){ divas_um_idi_entity_t *e = DIVAS_CONTAINING_RECORD(entity, divas_um_idi_entity_t, e); diva_os_spin_lock_magic_t old_irql; int call_wakeup = 0; diva_os_enter_spin_lock(&adapter_lock, &old_irql, "xdi_callback"); if (e->e.complete == 255) { if (!(e->status & DIVA_UM_IDI_REMOVE_PENDING)) { diva_um_idi_stop_wdog(e); } if ((call_wakeup = process_idi_rc(e, e->e.Rc))) { if (e->rc_count) { e->rc_count--; } } e->e.Rc = 0; diva_os_leave_spin_lock(&adapter_lock, &old_irql, "xdi_callback"); if (call_wakeup) { diva_os_wakeup_read(e->os_context); diva_os_wakeup_close(e->os_context); } } else { if (e->status & DIVA_UM_IDI_REMOVE_PENDING) { e->e.RNum = 0; e->e.RNR = 2; } else { call_wakeup = process_idi_ind(e, e->e.Ind); } e->e.Ind = 0; diva_os_leave_spin_lock(&adapter_lock, &old_irql, "xdi_callback"); if (call_wakeup) { diva_os_wakeup_read(e->os_context); } }}static int process_idi_request(divas_um_idi_entity_t * e, const diva_um_idi_req_hdr_t * req){ int assign = 0; byte Req = (byte) req->Req; dword type = req->type & DIVA_UM_IDI_REQ_TYPE_MASK; if (!e->e.Id || !e->e.callback) { /* not assigned */ if (Req != ASSIGN) { DBG_ERR(("A: A(%d) E(%08x) not assigned", e->adapter->adapter_nr, e)); return (-1); /* NOT ASSIGNED */ } else { switch (type) { case DIVA_UM_IDI_REQ_TYPE_MAN: e->e.Id = MAN_ID; DBG_TRC(("A(%d) E(%08x) assign MAN", e->adapter->adapter_nr, e)); break; case DIVA_UM_IDI_REQ_TYPE_SIG: e->e.Id = DSIG_ID; DBG_TRC(("A(%d) E(%08x) assign SIG", e->adapter->adapter_nr, e)); break; case DIVA_UM_IDI_REQ_TYPE_NET: e->e.Id = NL_ID; DBG_TRC(("A(%d) E(%08x) assign NET", e->adapter->adapter_nr, e)); break; default: DBG_ERR(("A: A(%d) E(%08x) unknown type=%08x", e->adapter->adapter_nr, e, type)); return (-1); } } e->e.XNum = 1; e->e.RNum = 1; e->e.callback = diva_um_idi_xdi_callback; e->e.X = &e->XData; e->e.R = &e->RData; assign = 1; } e->status |= DIVA_UM_IDI_RC_PENDING; e->e.Req = Req; e->e.ReqCh = (byte) req->ReqCh; e->e.X->PLength = (word) req->data_length; e->e.X->P = (byte *) & req[1]; /* Our buffer is safe */ DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))", e->adapter->adapter_nr, e, e->e.Id, e->e.Req, e->e.ReqCh, e->e.X->PLength)); e->rc_count++; if (e->adapter && e->adapter->d.request) { diva_um_idi_start_wdog(e); (*(e->adapter->d.request)) (&e->e); } if (assign) { if (e->e.Rc == OUT_OF_RESOURCES) { /* XDI has no entities more, call was not forwarded to the card, no callback will be scheduled */ DBG_ERR(("A: A(%d) E(%08x) XDI out of entities", e->adapter->adapter_nr, e)); e->e.Id = 0; e->e.ReqCh = 0; e->e.RcCh = 0; e->e.Ind = 0; e->e.IndCh = 0; e->e.XNum = 0; e->e.RNum = 0; e->e.callback = NULL; e->e.X = NULL; e->e.R = NULL; write_return_code(e, ASSIGN_RC | OUT_OF_RESOURCES); return (-2); } else { e->status |= DIVA_UM_IDI_ASSIGN_PENDING; } } return (0);}static int process_idi_rc(divas_um_idi_entity_t * e, byte rc){ DBG_TRC(("A(%d) E(%08x) rc(%02x-%02x-%02x)", e->adapter->adapter_nr, e, e->e.Id, rc, e->e.RcCh)); if (e->status & DIVA_UM_IDI_ASSIGN_PENDING) { e->status &= ~DIVA_UM_IDI_ASSIGN_PENDING; if (rc != ASSIGN_OK) { DBG_ERR(("A: A(%d) E(%08x) ASSIGN failed", e->adapter->adapter_nr, e)); e->e.callback = NULL; e->e.Id = 0; e->e.Req = 0; e->e.ReqCh = 0; e->e.Rc = 0; e->e.RcCh = 0; e->e.Ind = 0; e->e.IndCh = 0; e->e.X = NULL; e->e.R = NULL; e->e.XNum = 0; e->e.RNum = 0; } } if ((e->e.Req == REMOVE) && e->e.Id && (rc == 0xff)) { DBG_ERR(("A: A(%d) E(%08x) discard OK in REMOVE", e->adapter->adapter_nr, e)); return (0); /* let us do it in the driver */ } if ((e->e.Req == REMOVE) && (!e->e.Id)) { /* REMOVE COMPLETE */ e->e.callback = NULL; e->e.Id = 0; e->e.Req = 0; e->e.ReqCh = 0; e->e.Rc = 0; e->e.RcCh = 0; e->e.Ind = 0; e->e.IndCh = 0; e->e.X = NULL; e->e.R = NULL; e->e.XNum = 0; e->e.RNum = 0; e->rc_count = 0; } if ((e->e.Req == REMOVE) && (rc != 0xff)) { /* REMOVE FAILED */ DBG_ERR(("A: A(%d) E(%08x) REMOVE FAILED", e->adapter->adapter_nr, e)); } write_return_code(e, rc); return (1);}static int process_idi_ind(divas_um_idi_entity_t * e, byte ind){ int do_wakeup = 0; if (e->e.complete != 0x02) { diva_um_idi_ind_hdr_t *pind = (diva_um_idi_ind_hdr_t *) diva_data_q_get_segment4write(&e->data); if (pind) { e->e.RNum = 1; e->e.R->P = (byte *) & pind[1]; e->e.R->PLength = (word) (diva_data_q_get_max_length(&e->data) - sizeof(*pind)); DBG_TRC(("A(%d) E(%08x) ind_1(%02x-%02x-%02x)-[%d-%d]", e->adapter->adapter_nr, e, e->e.Id, ind, e->e.IndCh, e->e.RLength, e->e.R->PLength)); } else { DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-RNR", e->adapter->adapter_nr, e, e->e.Id, ind, e->e.IndCh)); e->e.RNum = 0; e->e.RNR = 1; do_wakeup = 1; } } else { diva_um_idi_ind_hdr_t *pind = (diva_um_idi_ind_hdr_t *) (e->e.R->P); DBG_TRC(("A(%d) E(%08x) ind(%02x-%02x-%02x)-[%d]", e->adapter->adapter_nr, e, e->e.Id, ind, e->e.IndCh, e->e.R->PLength)); pind--; pind->type = DIVA_UM_IDI_IND; pind->hdr.ind.Ind = ind; pind->hdr.ind.IndCh = e->e.IndCh; pind->data_length = e->e.R->PLength; diva_data_q_ack_segment4write(&e->data, (int) (sizeof(*pind) + e->e.R->PLength)); do_wakeup = 1; } if ((e->status & DIVA_UM_IDI_RC_PENDING) && !e->rc.count) { do_wakeup = 0; } return (do_wakeup);}/* -------------------------------------------------------------------------- Write return code to the return code queue of entity -------------------------------------------------------------------------- */static int write_return_code(divas_um_idi_entity_t * e, byte rc){ diva_um_idi_ind_hdr_t *prc; if (!(prc = (diva_um_idi_ind_hdr_t *) diva_data_q_get_segment4write(&e->rc))) { DBG_ERR(("A: A(%d) E(%08x) rc(%02x) lost", e->adapter->adapter_nr, e, rc)); e->status &= ~DIVA_UM_IDI_RC_PENDING; return (-1); } prc->type = DIVA_UM_IDI_IND_RC; prc->hdr.rc.Rc = rc; prc->hdr.rc.RcCh = e->e.RcCh; prc->data_length = 0; diva_data_q_ack_segment4write(&e->rc, sizeof(*prc)); return (0);}/* -------------------------------------------------------------------------- Return amount of entries that can be bead from this entity or -1 if adapter was removed -------------------------------------------------------------------------- */int diva_user_mode_idi_ind_ready(void *entity, void *os_handle){ divas_um_idi_entity_t *e; diva_um_idi_adapter_t *a; diva_os_spin_lock_magic_t old_irql; int ret; if (!entity) return (-1); diva_os_enter_spin_lock(&adapter_lock, &old_irql, "ind_ready"); e = (divas_um_idi_entity_t *) entity; a = e->adapter; if ((!a) || (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) { /* Adapter was unloaded */ diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready"); return (-1); /* adapter was removed */ } if (e->status & DIVA_UM_IDI_REMOVED) { /* entity was removed as result of adapter removal user should assign this entity again */ diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready"); return (-1); } ret = e->rc.count + e->data.count; if ((e->status & DIVA_UM_IDI_RC_PENDING) && !e->rc.count) { ret = 0; } diva_os_leave_spin_lock(&adapter_lock, &old_irql, "ind_ready"); return (ret);}void *diva_um_id_get_os_context(void *entity){ return (((divas_um_idi_entity_t *) entity)->os_context);}int divas_um_idi_entity_assigned(void *entity){ divas_um_idi_entity_t *e; diva_um_idi_adapter_t *a; int ret; diva_os_spin_lock_magic_t old_irql; diva_os_enter_spin_lock(&adapter_lock, &old_irql, "assigned?"); e = (divas_um_idi_entity_t *) entity; if (!e || (!(a = e->adapter)) || (e->status & DIVA_UM_IDI_REMOVED) || (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) { diva_os_leave_spin_lock(&adapter_lock, &old_irql, "assigned?"); return (0); } e->status |= DIVA_UM_IDI_REMOVE_PENDING; ret = (e->e.Id || e->rc_count || (e->status & DIVA_UM_IDI_ASSIGN_PENDING)); DBG_TRC(("Id:%02x, rc_count:%d, status:%08x", e->e.Id, e->rc_count, e->status)) diva_os_leave_spin_lock(&adapter_lock, &old_irql, "assigned?"); return (ret);}int divas_um_idi_entity_start_remove(void *entity){ divas_um_idi_entity_t *e; diva_um_idi_adapter_t *a; diva_os_spin_lock_magic_t old_irql; diva_os_enter_spin_lock(&adapter_lock, &old_irql, "start_remove"); e = (divas_um_idi_entity_t *) entity; if (!e || (!(a = e->adapter)) || (e->status & DIVA_UM_IDI_REMOVED) || (a->status & DIVA_UM_IDI_ADAPTER_REMOVED)) { diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove"); return (0); } if (e->rc_count) { /* Entity BUSY */ diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove"); return (1); } if (!e->e.Id) { /* Remove request was already pending, and arrived now */ diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove"); return (0); /* REMOVE was pending */ } /* Now send remove request */ e->e.Req = REMOVE; e->e.ReqCh = 0; e->rc_count++; DBG_TRC(("A(%d) E(%08x) request(%02x-%02x-%02x (%d))", e->adapter->adapter_nr, e, e->e.Id, e->e.Req, e->e.ReqCh, e->e.X->PLength)); if (a->d.request) (*(a->d.request)) (&e->e); diva_os_leave_spin_lock(&adapter_lock, &old_irql, "start_remove"); return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -