static void _reject(isc_session_t *sp, pduq_t *pq) { pduq_t *opq; pdu_t *pdu; reject_t *reject; int itt; debug_called(8); pdu = mtod(pq->mp, pdu_t *); itt = pdu->ipdu.bhs.itt; reject = &pq->pdu.ipdu.reject; sdebug(2, "itt=%x reason=0x%x", ntohl(itt), reject->reason); opq = i_search_hld(sp, itt, 0); if(opq != NULL) iscsi_reject(sp, opq, pq); else { switch(pq->pdu.ipdu.bhs.opcode) { case ISCSI_LOGOUT_CMD: // XXX: wasabi does this - can't figure out why sdebug(2, "ISCSI_LOGOUT_CMD ..."); break; default: xdebug("%d] we lost something itt=%x", sp->sid, ntohl(pq->pdu.ipdu.bhs.itt)); } } pdu_free(sp->isc, pq); }
static int ic_scan(isc_session_t *sp) { union ccb *ccb; debug_called(8); sdebug(2, "scanning sid=%d", sp->sid); sp->flags &= ~ISC_CAMDEVS; sp->flags |= ISC_SCANWAIT; ccb = xpt_alloc_ccb(); ccb->ccb_h.path = sp->cam_path; ccb->ccb_h.cbfcnp = scan_callback; ccb->ccb_h.spriv_ptr0 = sp; xpt_rescan(ccb); while(sp->flags & ISC_SCANWAIT) tsleep(sp, PRIBIO, "ffp", 5*hz); // the timeout time should // be configurable sdebug(2, "# of luns=%d", sp->target_nluns); if(sp->target_nluns > 0) { sp->flags |= ISC_CAMDEVS; return 0; } return ENODEV; }
/* | this is a kludge, | the jury is not back with a veredict, user or kernel */ static void _nop_out(isc_session_t *sp) { pduq_t *pq; nop_out_t *nop_out; debug_called(8); sdebug(4, "cws=%d", sp->cws); if(sp->cws == 0) { /* | only send a nop if window is closed. */ if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL) // I guess we ran out of resources return; nop_out = &pq->pdu.ipdu.nop_out; nop_out->opcode = ISCSI_NOP_OUT; nop_out->itt = htonl(sp->sn.itt); nop_out->ttt = -1; nop_out->I = 1; nop_out->F = 1; if(isc_qout(sp, pq) != 0) { sdebug(1, "failed"); pdu_free(sp->isc, pq); } } }
void TH__setup_threads(const TH_thread_funptr *thfptrs){ debug((uint16_t) thfptrs[0].fptr); int16_t i, n; debug(F("Tset:")); assert(thfptrs); TH__thread_funptrs = (TH_thread_funptr *)thfptrs; i = get_len_fptrs(); sdebug(F("len:")); edebug(i); assert(i <= MAX_THREADS); TH__threads = (pthread *)malloc(sizeof(pthread) * i); debug((uint16_t) TH__threads); memcheck(TH__threads); for(n = 0; n < i; n++){ //PT_INIT(&TH__threads[n]); //set_thread_innactive(&TH__threads[n]); TH__threads[n].lc = PT_INNACTIVE; TH__threads[n].data = NULL; } TH__threads_len = i; debug(F("TsetD")); return; error: memclr(TH__threads); return; }
/** * Initializes a counter object. This function is called by the oesr_counter_create(). * It calls nod_module_variable_create() to create a new module variable, which is associated to the * counter. Then uses nod_variable_init() to allocate the memory. */ int oesr_counter_init(void *context, oesr_counter_t *counter, string name) { sdebug("context=0x%x, counter_id=%d, name=%s\n",context,counter->id,name); oesr_context_t *ctx = context; nod_module_t *module = ctx->module; OESR_ASSERT_PARAM(counter); OESR_ASSERT_PARAM(name); variable_t *variable = nod_module_variable_create(module, name,0); if (!variable) { return -1; } variable->size = sizeof(int); variable->cur_value = &counter->count[0].tv_usec; sdebug("variable_id=%d, addr=0x%x\n",variable->id,variable->cur_value); counter->variable = variable; counter->context = ctx; return 0; }
/** Returns the module id (non-negative integer), -1 on error */ int oesr_module_id(void *context) { cast(ctx,context); nod_module_t *module = (nod_module_t*) ctx->module; sdebug("context=0x%x, module_id=%d, module_name=0x%x\n",context,module->parent.id, module->parent.name); return module->parent.id; }
int ic_init(isc_session_t *sp) { struct cam_sim *sim; struct cam_devq *devq; debug_called(8); if((devq = cam_simq_alloc(256)) == NULL) return ENOMEM; #if __FreeBSD_version >= 700000 mtx_init(&sp->cam_mtx, "isc-cam", NULL, MTX_DEF); #else isp->cam_mtx = Giant; #endif sim = cam_sim_alloc(ic_action, ic_poll, "iscsi", sp, sp->sid, // unit #if __FreeBSD_version >= 700000 &sp->cam_mtx, #endif 1, // max_dev_transactions 0, // max_tagged_dev_transactions devq); if(sim == NULL) { cam_simq_free(devq); #if __FreeBSD_version >= 700000 mtx_destroy(&sp->cam_mtx); #endif return ENXIO; } CAM_LOCK(sp); if(xpt_bus_register(sim, #if __FreeBSD_version >= 700000 NULL, #endif 0/*bus_number*/) != CAM_SUCCESS) { cam_sim_free(sim, /*free_devq*/TRUE); CAM_UNLOCK(sp); #if __FreeBSD_version >= 700000 mtx_destroy(&sp->cam_mtx); #endif return ENXIO; } sp->cam_sim = sim; CAM_UNLOCK(sp); sdebug(1, "cam subsystem initialized"); ic_scan(sp); return 0; }
static int ic_scan(isc_session_t *sp) { union ccb *ccb; debug_called(8); sdebug(2, "scanning sid=%d", sp->sid); if((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK | M_ZERO)) == NULL) { xdebug("scan failed (can't allocate CCB)"); return ENOMEM; // XXX } sp->flags &= ~ISC_CAMDEVS; sp->flags |= ISC_SCANWAIT; CAM_LOCK(sp); if(xpt_create_path(&sp->cam_path, NULL, cam_sim_path(sp->cam_sim), 0, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xdebug("can't create cam path"); CAM_UNLOCK(sp); free(ccb, M_TEMP); return ENODEV; // XXX } xpt_setup_ccb(&ccb->ccb_h, sp->cam_path, 5/*priority (low)*/); ccb->ccb_h.func_code = XPT_SCAN_BUS; ccb->ccb_h.cbfcnp = scan_callback; ccb->crcn.flags = CAM_FLAG_NONE; ccb->ccb_h.spriv_ptr0 = sp; xpt_action(ccb); CAM_UNLOCK(sp); while(sp->flags & ISC_SCANWAIT) tsleep(sp, PRIBIO, "ffp", 5*hz); // the timeout time should // be configurable sdebug(2, "# of luns=%d", sp->target_nluns); if(sp->target_nluns > 0) { sp->flags |= ISC_CAMDEVS; return 0; } return ENODEV; }
/** * Starts the counter clock. * * \param counter Value returned by the oesr_counter_create() function * \returns 0 on success or -1 on error. */ int oesr_counter_start(counter_t counter) { oesr_counter_t *cnt = (oesr_counter_t*) counter; oesr_context_t *ctx = cnt->context; OESR_ASSERT_PARAM(counter); rtdal_time_get(&cnt->count[1]); sdebug("context=0x%x, counter_id=%d, start=%d:%d\n",ctx,cnt->id, cnt->count[1].tv_sec,cnt->count[1].tv_usec); return -1; }
/** * Writes the buffer str to the log file associated to the handler log. * Only up to LSTR_LEN characters of the string will be copied to the log buffer. * * \param log Handler obtained by oesr_log_create() * \param str String to write to the buffer * * \returns 0 on success, -1 on error */ int oesr_log_write(log_t log, char *str) { oesr_log_t *l = (oesr_log_t*) log; oesr_context_t *ctx = l->context; OESR_ASSERT_PARAM(log); OESR_ASSERT_PARAM(str); sdebug("log_id=%s, buffer_len=%d\n",l->id, strnlen(l->buffer,LSTR_LEN)); strncat(l->buffer,str,LSTR_LEN); return 0; }
/** * Returns the parameter variable type (see enum oesr_var_type_t) * \param context OESR context pointer * \param parameter Handler returned by the oesr_var_param_get() function. */ oesr_var_type_t oesr_var_param_type(void *context, var_t parameter) { cast(ctx,context); sdebug("id=0x%x\n",parameter); OESR_ASSERT_PARAM(parameter); variable_t *variable = (variable_t*) parameter; return (oesr_var_type_t) variable->type; }
/** Sets up to size bytes of the value of the parameter to the value of the * buffer pointed by ptr to the * * \param context OESR context pointer * \param parameter Handler returned by the oesr_var_param_get() function. * \param value Pointer to the user memory where the parameter value will be stored * \param size Size of user memory buffer * * \return On success, returns a non-negative integer indicating the number of bytes written to value. * On error returns -1 */ int oesr_var_param_set_value(void *context, var_t parameter, void* value, int size) { int cpy_sz; cast(ctx,context); sdebug("set_value id=0x%x, size=%d\n",parameter,size); OESR_ASSERT_PARAM(parameter); OESR_ASSERT_PARAM(value); OESR_ASSERT_PARAM(size>0); nod_module_t *module = (nod_module_t*) ctx->module; variable_t *variable = (variable_t*) parameter; cpy_sz = (size > variable->size)?variable->size:size; memcpy(variable->init_value[module->parent.mode.cur_mode], value, (size_t) cpy_sz); sdebug("id=0x%x, copied=%d\n", parameter, cpy_sz); return cpy_sz; }
/** * Called from oesr_log_create. Initializes the structure and creates the associated * filename for writing logs. */ int oesr_log_init(void *context, oesr_log_t *log, string name) { oesr_context_t *ctx = context; nod_module_t *module = ctx->module; sdebug("log_name=%s\n",name); lstrdef(tmp); OESR_ASSERT_PARAM(log); OESR_ASSERT_PARAM(name); snprintf(tmp,LSTR_LEN,"%s.%s",module->parent.name,name); sdebug("filename=%s\n",tmp); int fd = rtdal_file_open(tmp); if (fd < 0) { OESR_HWERROR("rtdal_file_open"); return -1; } sdebug("log_fd=%d\n",fd); log->fd = fd; log->context = ctx; strcpy(log->name,name); return 0; }
/** * * oesr_counter_create() creates a new counter. It returns a handler that is then used by the * counter functions to manage it. * * \param context OESR context pointer * \param name Name associated to the public variable * \returns On success, returns a non-null counter_t object. On error returns null. */ counter_t oesr_counter_create(void *context, char *name) { sdebug("context=0x%x, name=%s\n",context,name); cast_p(ctx,context); OESR_ASSERT_PARAM_P(name); int i; i=0; while(i<MAX(oesr_counter) && ctx->counters[i].id) i++; if (i==MAX(oesr_counter)) { OESR_SETERROR(OESR_ERROR_NOSPACE); return NULL; } sdebug("counter_pos=%d\n",i); if (oesr_counter_init(ctx, &ctx->counters[i],name)) { return NULL; } else { ctx->counters[i].id = i+1; return (counter_t) &ctx->counters[i]; } }
/** * Stops the calling module execution. Sets the module as NON-runnable. * * The module continues the execution after this function returns but, once the module returns from one * of the Init/Run/Stop functions, it will not be executed again. * The oesr_exit() function DOES NOT free the module's resources. In the case of a normal STOP, * this is done by the the OESR using the rtdal_process_remove() function. */ int oesr_exit(void *context) { cast(ctx,context); nod_module_t *module = (nod_module_t*) ctx->module; sdebug("module_id=%d, cur_status=%d\n",module->parent.id, module->parent.status); if (!module->process) { return -1; } if (rtdal_process_stop(module->process)) { return -1; } return 0; }
/** * Returns a handler for the parameter with name "name". * This handler is then used by the functions oesr_var_param_value() and oesr_var_param_type() * * \param context OESR context pointer * \param name Name of the parameter, as it appears in the waveform .app file * \return On success, returns a non-null handler. On error returns null. */ var_t oesr_var_param_get(void *context, char *name) { cast_p(ctx,context); OESR_ASSERT_PARAM_P(name); sdebug("name=%s\n",name); nod_module_t *module = (nod_module_t*) ctx->module; variable_t *variable = nod_module_variable_get(module,name); if (!variable) { OESR_SETERROR(OESR_ERROR_NOTFOUND); return NULL; } return (var_t) variable; }
void ic_destroy(isc_session_t *sp ) { debug_called(8); if(sp->cam_path != NULL) { sdebug(2, "name=%s unit=%d", cam_sim_name(sp->cam_sim), cam_sim_unit(sp->cam_sim)); CAM_LOCK(sp); #if 0 xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL); #else xpt_async(XPT_RESET_BUS, sp->cam_path, NULL); #endif xpt_free_path(sp->cam_path); xpt_bus_deregister(cam_sim_path(sp->cam_sim)); cam_sim_free(sp->cam_sim, TRUE /*free_devq*/); CAM_UNLOCK(sp); sdebug(2, "done"); } }
/** * Stops the counter clock and sets the elapsed time. * * \param counter Value returned by the oesr_counter_create() function * \returns 0 on success or -1 on error. */ int oesr_counter_stop(counter_t counter) { oesr_counter_t *cnt = (oesr_counter_t*) counter; oesr_context_t *ctx = cnt->context; OESR_ASSERT_PARAM(counter); variable_t *variable = cnt->variable; rtdal_time_get(&cnt->count[2]); rtdal_time_interval(cnt->count); sdebug("context=0x%x, counter_id=%d, finish=%d:%d, count=%d, value=0x%x\n",ctx,cnt->id, cnt->count[2].tv_sec,cnt->count[2].tv_usec,cnt->count[0].tv_usec, variable->cur_value); return 0; }
/** * Closes a log associated to the handler passed as parameter. * \param log Handler obtained by oesr_log_create() * * \returns 0 on success, -1 on error */ int oesr_log_close(log_t log) { oesr_log_t *l = (oesr_log_t*) log; oesr_context_t *ctx = l->context; sdebug("log_id=%s, fd=%d\n",l->id, l->fd); OESR_ASSERT_PARAM(log); if (rtdal_file_close(l->fd)) { OESR_HWERROR("rtdal_file_close"); return -1; } l->fd = 0; l->id = 0; return 0; }
/** Sets up to size bytes of the value of the parameter to the value of the * buffer pointed by ptr to the * * \param context OESR context pointer * \param idx Index of the parameter in the local database * \param value Pointer to the user memory where the parameter value will be stored * \param size Size of user memory buffer * * \return On success, returns a non-negative integer indicating the number of bytes written to value. * On error returns -1 */ int oesr_var_param_set_value_idx(void *context, int idx, void* value, int size) { int cpy_sz; cast(ctx,context); sdebug("%s: set_value_idx idx=%d, value 0x%x size=%d\n",oesr_module_name(ctx),idx,value,size); OESR_ASSERT_PARAM(idx>=0); OESR_ASSERT_PARAM(value); OESR_ASSERT_PARAM(size>0); nod_module_t *module = (nod_module_t*) ctx->module; variable_t *variable = (variable_t*) &module->parent.variables[idx]; sdebug("%s: %d:%s: set variable %s value %d\n",oesr_module_name(ctx),oesr_tstamp(context), module->parent.name,variable->name,*((int*) value)); cpy_sz = (size > variable->size)?variable->size:size; memcpy(variable->init_value[module->parent.mode.cur_mode], value, (size_t) cpy_sz); sdebug("id=0x%x, copied=%d\n", variable, cpy_sz); return cpy_sz; }
uint8_t schedule_thread(pthread *th){ uint8_t out = false; TH_funptr tfun; sdebug(F("schT:")); edebug(get_index(th)); assert(thread_exists(th)); assert_raise(not is_active(th), ERR_VALUE, th->lc); debug("Init"); PT_INIT(th); tfun = get_thread_function(get_index(th)); assert(tfun); out = tfun(th); if(out >= PT_EXITED){ set_thread_innactive(th); out = true; sdebug("Ts:"); edebug(get_index(th)); } else{ sdebug("Ts:"); edebug(get_index(th)); out = true; } error: return out; }
void ic_lost_target(isc_session_t *sp, int target) { debug_called(8); sdebug(2, "lost target=%d", target); if(sp->cam_path != NULL) { mtx_lock(&sp->cam_mtx); xpt_async(AC_LOST_DEVICE, sp->cam_path, NULL); xpt_free_path(sp->cam_path); mtx_unlock(&sp->cam_mtx); sp->cam_path = 0; // XXX } }
/** * * oesr_counter_close() closes a counter and deallocates its resources. The counter can not be used * after a call to this function. * * \param counter Value returned by the oesr_counter_create() function * \returns 0 if successfully closed or -1 on error. */ int oesr_counter_close(counter_t counter) { oesr_counter_t *cnt = (oesr_counter_t*) counter; oesr_context_t *ctx = cnt->context; sdebug("context=0x%x, counter_id=%d\n",ctx,cnt->id); OESR_ASSERT_PARAM(counter); variable_t *variable = cnt->variable; if (variable) { variable->id = 0; variable->size = 0; } cnt->id = 0; cnt->variable = NULL; return 0; }
var_t oesr_var_param_create_remote(void *context, int module_idx, char *name, int size) { oesr_context_t *ctx = context; OESR_ASSERT_PARAM_P(name); sdebug("remote_idx=%d name=%s, size=%d\n",module_idx,name,size); OESR_ASSERT_PARAM_P(module_idx); OESR_ASSERT_PARAM_P(size>=0); nod_module_t *my_module = ctx->module; nod_waveform_t *waveform = (nod_waveform_t*) my_module->parent.waveform; nod_module_t *his_module = (nod_module_t*) &waveform->modules[module_idx]; return (var_t) nod_module_variable_create(his_module, name, size); }
/** Sets up to size bytes of the buffer pointed by ptr to the value of the parameter * returned by oesr_var_param_get() * * \param context OESR context pointer * \param parameter Handler returned by the oesr_var_param_get() function. * \param value Pointer to the user memory where the parameter value will be stored * \param size Size of user memory buffer * * \return On success, returns a non-negative integer indicating the number of bytes written to value. * On error returns -1 */ int oesr_var_param_get_value(void *context, var_t parameter, void* value, int size) { int cpy_sz; cast(ctx,context); OESR_ASSERT_PARAM(parameter); OESR_ASSERT_PARAM(value); OESR_ASSERT_PARAM(size>0); nod_module_t *module = (nod_module_t*) ctx->module; variable_t *variable = (variable_t*) parameter; sdebug("id=0x%x, size=%d, value=0x%x, cur_mode=%d\n",parameter,size,value,module->parent.mode.cur_mode); cpy_sz = (variable->size > size)?size:variable->size; if (module->parent.mode.next_tslot && module->parent.mode.next_tslot <= rtdal_time_slot()) { module->parent.mode.cur_mode = module->parent.mode.next_mode; module->parent.mode.next_tslot = 0; } memcpy(value, variable->init_value[module->parent.mode.cur_mode], (size_t) cpy_sz); sdebug("id=0x%x, copied=%d\n", variable, cpy_sz); return cpy_sz; }
/** * Fills the buffer parameters with up to max_elems module parameters defined in the app * * \param context OESR context pointer * \param parameter Pointer to a parameters buffer * \param max_elems Size of the parameters buffer * * \return On success, returns a non-negative number indicating the number of parameters * successfully copied to the buffer, on error returns -1 */ int oesr_var_param_list(void *context, var_t *parameters, int max_elems) { cast(ctx,context); int i; OESR_ASSERT_PARAM(parameters); OESR_ASSERT_PARAM(max_elems>=0); nod_module_t *module = (nod_module_t*) ctx->module; if (max_elems > module->parent.nof_variables) { max_elems = module->parent.nof_variables; } for (i=0;i<max_elems;i++) { parameters[i] = (var_t) &module->parent.variables[i]; sdebug("list %d %s id=0x%x size %d\n",i,module->parent.variables[i].name, parameters[i],module->parent.variables[i].size); } return max_elems; }
/** * It creates a new log for the module. The returned handler (if non-null) * is then passed as the first parameter to the functions oesr_log_write() or oesr_log_printf(). * \param context OESR context pointer * \param name Name of the log to create * \returns NULL on error or non-null on success. */ log_t oesr_log_create(void *context, char *name) { sdebug("context=0x%x, name=%s\n",context,name); cast_p(ctx,context); OESR_ASSERT_PARAM_P(name); int i; i=0; while(i<MAX(oesr_log) && ctx->logs[i].id) i++; if (i==MAX(oesr_log)) { OESR_SETERROR(OESR_ERROR_NOSPACE); return NULL; } if (oesr_log_init(ctx, &ctx->logs[i], name)) { return NULL; } ctx->logs[i].id = i+1; return (log_t) &ctx->logs[i]; }
/** * Creates a new public variable with a given name. After this call size bytes of the buffer ptr may be * accessible by other modules or ALOE (through the OESR Manager API) for either read or write. * * \param context OESR context pointer * \param name Name of the variable. This name will be used by other modules or the OESR Manager API to * view/modify the variable value * \param ptr Pointer to the user memory where the variable is located * \param size Size of the variable * \return On success, oesr_var_create() returns a non-null handler which is passed as a first parameter * to oesr_var_close() to close the public variable. * */ var_t oesr_var_create(void *context, char *name, void *ptr, int size) { oesr_context_t *ctx = context; nod_module_t *module = ctx->module; OESR_ASSERT_PARAM_P(name); sdebug("name=%s, size=%d, ptr=0x%x\n",name,size,ptr); OESR_ASSERT_PARAM_P(module); OESR_ASSERT_PARAM_P(size>0); OESR_ASSERT_PARAM_P(ptr); variable_t *variable; variable = nod_module_variable_get(module, name); if (!variable) { variable = nod_module_variable_create(module, name,0); if (!variable) { return NULL; } } variable->size = size; variable->cur_value = ptr; return 0; }
void Tracer::debug(const char* method, const char* message, ...) const { // immediately return if the current set tracelevel is higher if (m_tracelevel > LEVEL_DEBUG) { return; } ///@todo with qt4 the follwing code can be used: /* va_list ap; va_start(ap, message); QString str; str.vsprintf(message, ap); va_end(ap); sdebug(method) << str << endl; */ va_list ap; int maxLength = 1024; int result = maxLength; char* str; while (result >= maxLength) { va_start(ap, message); str = (char*)malloc(maxLength); result = vsnprintf(str, maxLength-1, message, ap); va_end(ap); if (result >= maxLength) { delete str; maxLength = 2 * maxLength; result = maxLength; } } sdebug(method) << str << endl; delete str; }
/* | Add header digest to the iSCSI hdr mbuf | XXX Assert: (mh->m_pkthdr.len + 4) < MHLEN */ bcopy(&pp->hdr_dig, (mh->m_data + mh->m_len), sizeof(int)); mh->m_len += sizeof(int); mh->m_pkthdr.len += sizeof(int); } mp = &mh->m_next; if(pq->pdu.ds) { struct mbuf *md; int off = 0; len = pp->ds_len; while(len & 03) // the specs say it must be int alligned len++; while(len > 0) { int l; MGET(md, MB_TRYWAIT, MT_DATA); pq->refcnt++; l = min(MCLBYTES, len); debug(5, "setting ext_free(arg=%p len/l=%d/%d)", pq->buf, len, l); md->m_ext.ext_buf = pq->buf; md->m_ext.ext_free = ext_free; md->m_ext.ext_ref = ext_ref; md->m_ext.ext_arg = pq; md->m_ext.ext_size = l; md->m_flags |= M_EXT; md->m_data = pp->ds + off; md->m_len = l; md->m_next = NULL; mh->m_pkthdr.len += l; *mp = md; mp = &md->m_next; len -= l; off += l; } } if(sp->dataDigest) { struct mbuf *me; pp->ds_dig = sp->dataDigest(pp->ds, pp->ds_len, 0); MGET(me, MB_TRYWAIT, MT_DATA); me->m_len = sizeof(int); MH_ALIGN(mh, sizeof(int)); bcopy(&pp->ds_dig, me->m_data, sizeof(int)); me->m_next = NULL; mh->m_pkthdr.len += sizeof(int); *mp = me; } if((error = sosend(sp->soc, NULL, NULL, mh, 0, 0, curthread)) != 0) { sdebug(3, "error=%d", error); return error; } sp->stats.nsent++; getmicrouptime(&sp->stats.t_sent); return 0; } #else /* NO_USE_MBUF */ int isc_sendPDU(isc_session_t *sp, pduq_t *pq) { struct uio *uio = &pq->uio; struct iovec *iv; pdu_t *pp = &pq->pdu; int len, error; debug_called(8); bzero(uio, sizeof(struct uio)); uio->uio_rw = UIO_WRITE; uio->uio_segflg = UIO_SYSSPACE; uio->uio_td = curthread; uio->uio_iov = iv = pq->iov; iv->iov_base = &pp->ipdu; iv->iov_len = sizeof(union ipdu_u); uio->uio_resid = pq->len; iv++; if(sp->hdrDigest) pq->pdu.hdr_dig = sp->hdrDigest(&pp->ipdu, sizeof(union ipdu_u), 0); if(pp->ahs_len) { iv->iov_base = pp->ahs; iv->iov_len = pp->ahs_len; iv++; if(sp->hdrDigest) pq->pdu.hdr_dig = sp->hdrDigest(&pp->ahs, pp->ahs_len, pq->pdu.hdr_dig); } if(sp->hdrDigest) { debug(2, "hdr_dig=%x", pq->pdu.hdr_dig); iv->iov_base = &pp->hdr_dig; iv->iov_len = sizeof(int); iv++; } if(pq->pdu.ds) { iv->iov_base = pp->ds; iv->iov_len = pp->ds_len; while(iv->iov_len & 03) // the specs say it must be int alligned iv->iov_len++; iv++; } if(sp->dataDigest) { pp->ds_dig = sp->dataDigest(pp->ds, pp->ds_len, 0); iv->iov_base = &pp->ds_dig; iv->iov_len = sizeof(int); iv++; } uio->uio_iovcnt = iv - pq->iov; sdebug(5, "opcode=%x iovcnt=%d uio_resid=%d itt=%x", pp->ipdu.bhs.opcode, uio->uio_iovcnt, uio->uio_resid, ntohl(pp->ipdu.bhs.itt)); sdebug(5, "sp=%p sp->soc=%p uio=%p sp->td=%p", sp, sp->soc, uio, sp->td); do { len = uio->uio_resid; error = sosend(sp->soc, NULL, uio, 0, 0, 0, curthread); if(uio->uio_resid == 0 || error || len == uio->uio_resid) { if(uio->uio_resid) { sdebug(2, "uio->uio_resid=%d uio->uio_iovcnt=%d error=%d len=%d", uio->uio_resid, uio->uio_iovcnt, error, len); if(error == 0) error = EAGAIN; // 35 } break; } /* | XXX: untested code */ sdebug(1, "uio->uio_resid=%d uio->uio_iovcnt=%d", uio->uio_resid, uio->uio_iovcnt); iv = uio->uio_iov; len -= uio->uio_resid; while(uio->uio_iovcnt > 0) { if(iv->iov_len > len) { caddr_t bp = (caddr_t)iv->iov_base; iv->iov_len -= len; iv->iov_base = (void *)&bp[len]; break; } len -= iv->iov_len; uio->uio_iovcnt--; uio->uio_iov++; iv++; } } while(uio->uio_resid); if(error == 0) { sp->stats.nsent++; getmicrouptime(&sp->stats.t_sent); } return error; }