i4bioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) #endif { call_desc_t *cd; int error = 0; if(minor(dev)) return(ENODEV); switch(cmd) { /* cdid request, reserve cd and return cdid */ case I4B_CDID_REQ: { msg_cdid_req_t *mir; mir = (msg_cdid_req_t *)data; cd = reserve_cd(); mir->cdid = cd->cdid; break; } /* connect request, dial out to remote */ case I4B_CONNECT_REQ: { msg_connect_req_t *mcr; mcr = (msg_connect_req_t *)data; /* setup ptr */ if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */ { DBGL4(L4_ERR, "i4bioctl", ("I4B_CONNECT_REQ ioctl, cdid not found!\n")); error = EINVAL; break; } /* prevent dialling on leased lines */ if(ctrl_desc[mcr->controller].protocol == PROTOCOL_D64S) { SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B); SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_LLDIAL); i4b_l4_disconnect_ind(cd); freecd_by_cd(cd); break; } cd->controller = mcr->controller; /* fill cd */ cd->bprot = mcr->bprot; cd->driver = mcr->driver; cd->driver_unit = mcr->driver_unit; cd->cr = get_rand_cr(ctrl_desc[cd->controller].unit); cd->shorthold_data.shorthold_algorithm = mcr->shorthold_data.shorthold_algorithm; cd->shorthold_data.unitlen_time = mcr->shorthold_data.unitlen_time; cd->shorthold_data.idle_time = mcr->shorthold_data.idle_time; cd->shorthold_data.earlyhup_time = mcr->shorthold_data.earlyhup_time; cd->last_aocd_time = 0; if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC) cd->aocd_flag = 1; else cd->aocd_flag = 0; cd->cunits = 0; cd->max_idle_time = 0; /* this is outgoing */ cd->dir = DIR_OUTGOING; DBGL4(L4_TIMO, "i4bioctl", ("I4B_CONNECT_REQ times, algorithm=%ld unitlen=%ld idle=%ld earlyhup=%ld\n", (long)cd->shorthold_data.shorthold_algorithm, (long)cd->shorthold_data.unitlen_time, (long)cd->shorthold_data.idle_time, (long)cd->shorthold_data.earlyhup_time)); strcpy(cd->dst_telno, mcr->dst_telno); strcpy(cd->src_telno, mcr->src_telno); cd->display[0] = '\0'; SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B); SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL); switch(mcr->channel) { case CHAN_B1: case CHAN_B2: if(ctrl_desc[mcr->controller].bch_state[mcr->channel] != BCH_ST_FREE) SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); break; case CHAN_ANY: if((ctrl_desc[mcr->controller].bch_state[CHAN_B1] != BCH_ST_FREE) && (ctrl_desc[mcr->controller].bch_state[CHAN_B2] != BCH_ST_FREE)) SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); break; default: SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); break; } cd->channelid = mcr->channel; cd->isdntxdelay = mcr->txdelay; /* check whether we have a pointer. Seems like */ /* this should be adequate. GJ 19.09.97 */ if(ctrl_desc[cd->controller].N_CONNECT_REQUEST == NULL) /*XXX*/ SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL) { i4b_l4_disconnect_ind(cd); freecd_by_cd(cd); } else { (*ctrl_desc[cd->controller].N_CONNECT_REQUEST)(mcr->cdid); } break; } /* connect response, accept/reject/ignore incoming call */ case I4B_CONNECT_RESP: { msg_connect_resp_t *mcrsp; mcrsp = (msg_connect_resp_t *)data; if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */ { DBGL4(L4_ERR, "i4bioctl", ("I4B_CONNECT_RESP ioctl, cdid not found!\n")); error = EINVAL; break; } T400_stop(cd); cd->driver = mcrsp->driver; cd->driver_unit = mcrsp->driver_unit; cd->max_idle_time = mcrsp->max_idle_time; cd->shorthold_data.shorthold_algorithm = SHA_FIXU; cd->shorthold_data.unitlen_time = 0; /* this is incoming */ cd->shorthold_data.idle_time = 0; cd->shorthold_data.earlyhup_time = 0; cd->isdntxdelay = mcrsp->txdelay; DBGL4(L4_TIMO, "i4bioctl", ("I4B_CONNECT_RESP max_idle_time set to %ld seconds\n", (long)cd->max_idle_time)); (*ctrl_desc[cd->controller].N_CONNECT_RESPONSE)(mcrsp->cdid, mcrsp->response, mcrsp->cause); break; } /* disconnect request, actively terminate connection */ case I4B_DISCONNECT_REQ: { msg_discon_req_t *mdr; mdr = (msg_discon_req_t *)data; if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */ { DBGL4(L4_ERR, "i4bioctl", ("I4B_DISCONNECT_REQ ioctl, cdid not found!\n")); error = EINVAL; break; } /* preset causes with our cause */ cd->cause_in = cd->cause_out = mdr->cause; (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(mdr->cdid, mdr->cause); break; } /* controller info request */ case I4B_CTRL_INFO_REQ: { msg_ctrl_info_req_t *mcir; mcir = (msg_ctrl_info_req_t *)data; mcir->ncontroller = nctrl; if(mcir->controller > nctrl) { mcir->ctrl_type = -1; mcir->card_type = -1; } else { mcir->ctrl_type = ctrl_desc[mcir->controller].ctrl_type; mcir->card_type = ctrl_desc[mcir->controller].card_type; if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE) mcir->tei = ctrl_desc[mcir->controller].tei; else mcir->tei = -1; } break; } /* dial response */ case I4B_DIALOUT_RESP: { drvr_link_t *dlt = NULL; msg_dialout_resp_t *mdrsp; mdrsp = (msg_dialout_resp_t *)data; switch(mdrsp->driver) { #if NI4BIPR > 0 case BDRV_IPR: dlt = ipr_ret_linktab(mdrsp->driver_unit); break; #endif #if NI4BISPPP > 0 case BDRV_ISPPP: dlt = i4bisppp_ret_linktab(mdrsp->driver_unit); break; #endif #if NI4BTEL > 0 case BDRV_TEL: dlt = tel_ret_linktab(mdrsp->driver_unit); break; #endif #if NIBC > 0 case BDRV_IBC: dlt = ibc_ret_linktab(mdrsp->driver_unit); break; #endif } if(dlt != NULL) (*dlt->dial_response)(mdrsp->driver_unit, mdrsp->stat, mdrsp->cause); break; } /* update timeout value */ case I4B_TIMEOUT_UPD: { msg_timeout_upd_t *mtu; int x; mtu = (msg_timeout_upd_t *)data; DBGL4(L4_TIMO, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, alg %d, unit %d, idle %d, early %d!\n", mtu->shorthold_data.shorthold_algorithm, mtu->shorthold_data.unitlen_time, mtu->shorthold_data.idle_time, mtu->shorthold_data.earlyhup_time )); if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */ { DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, cdid not found!\n")); error = EINVAL; break; } switch( mtu->shorthold_data.shorthold_algorithm ) { case SHA_FIXU: /* * For this algorithm unitlen_time, * idle_time and earlyhup_time are used. */ if(!(mtu->shorthold_data.unitlen_time >= 0 && mtu->shorthold_data.idle_time >= 0 && mtu->shorthold_data.earlyhup_time >= 0)) { DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, invalid args for fix unit algorithm!\n")); error = EINVAL; } break; case SHA_VARU: /* * For this algorithm unitlen_time and * idle_time are used. both must be * positive integers. earlyhup_time is * not used and must be 0. */ if(!(mtu->shorthold_data.unitlen_time > 0 && mtu->shorthold_data.idle_time >= 0 && mtu->shorthold_data.earlyhup_time == 0)) { DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, invalid args for var unit algorithm!\n")); error = EINVAL; } break; default: DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, invalid algorithm!\n")); error = EINVAL; break; } /* * any error set above requires us to break * out of the outer switch */ if(error != 0) break; x = SPLI4B(); cd->shorthold_data.shorthold_algorithm = mtu->shorthold_data.shorthold_algorithm; cd->shorthold_data.unitlen_time = mtu->shorthold_data.unitlen_time; cd->shorthold_data.idle_time = mtu->shorthold_data.idle_time; cd->shorthold_data.earlyhup_time = mtu->shorthold_data.earlyhup_time; splx(x); break; } /* soft enable/disable interface */ case I4B_UPDOWN_IND: { msg_updown_ind_t *mui; mui = (msg_updown_ind_t *)data; #if NI4BIPR > 0 if(mui->driver == BDRV_IPR) { drvr_link_t *dlt; dlt = ipr_ret_linktab(mui->driver_unit); (*dlt->updown_ind)(mui->driver_unit, mui->updown); } #endif break; } /* send ALERT request */ case I4B_ALERT_REQ: { msg_alert_req_t *mar; mar = (msg_alert_req_t *)data; if((cd = cd_by_cdid(mar->cdid)) == NULL) { DBGL4(L4_ERR, "i4bioctl", ("I4B_ALERT_REQ ioctl, cdid not found!\n")); error = EINVAL; break; } T400_stop(cd); (*ctrl_desc[cd->controller].N_ALERT_REQUEST)(mar->cdid); break; } /* version/release number request */ case I4B_VR_REQ: { msg_vr_req_t *mvr; mvr = (msg_vr_req_t *)data; mvr->version = VERSION; mvr->release = REL; mvr->step = STEP; break; } /* set D-channel protocol for a controller */ case I4B_PROT_IND: { msg_prot_ind_t *mpi; mpi = (msg_prot_ind_t *)data; ctrl_desc[mpi->controller].protocol = mpi->protocol; break; } /* Download request */ case I4B_CTRL_DOWNLOAD: { struct isdn_dr_prot *prots = NULL, *prots2 = NULL; struct isdn_download_request *r = (struct isdn_download_request*)data; int i; if (r->controller < 0 || r->controller >= nctrl) { error = ENODEV; goto download_done; } if(!ctrl_desc[r->controller].N_DOWNLOAD) { error = ENODEV; goto download_done; } prots = malloc(r->numprotos * sizeof(struct isdn_dr_prot), M_DEVBUF, M_WAITOK); prots2 = malloc(r->numprotos * sizeof(struct isdn_dr_prot), M_DEVBUF, M_WAITOK); if(!prots || !prots2) { error = ENOMEM; goto download_done; } copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot)); for(i = 0; i < r->numprotos; i++) { prots2[i].microcode = malloc(prots[i].bytecount, M_DEVBUF, M_WAITOK); copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount); prots2[i].bytecount = prots[i].bytecount; } error = ctrl_desc[r->controller].N_DOWNLOAD( ctrl_desc[r->controller].unit, r->numprotos, prots2); download_done: if(prots2) { for(i = 0; i < r->numprotos; i++) { if(prots2[i].microcode) { free(prots2[i].microcode, M_DEVBUF); } } free(prots2, M_DEVBUF); } if(prots) { free(prots, M_DEVBUF); } break; } /* Diagnostic request */ case I4B_ACTIVE_DIAGNOSTIC: { struct isdn_diagnostic_request req, *r = (struct isdn_diagnostic_request*)data; req.in_param = req.out_param = NULL; if (r->controller < 0 || r->controller >= nctrl) { error = ENODEV; goto diag_done; } if(!ctrl_desc[r->controller].N_DIAGNOSTICS) { error = ENODEV; goto diag_done; } memcpy(&req, r, sizeof(req)); if(req.in_param_len) { req.in_param = malloc(r->in_param_len, M_DEVBUF, M_WAITOK); if(!req.in_param) { error = ENOMEM; goto diag_done; } error = copyin(r->in_param, req.in_param, req.in_param_len); if (error) goto diag_done; } if(req.out_param_len) { req.out_param = malloc(r->out_param_len, M_DEVBUF, M_WAITOK); if(!req.out_param) { error = ENOMEM; goto diag_done; } } error = ctrl_desc[r->controller].N_DIAGNOSTICS(r->controller, &req); if(!error && req.out_param_len) error = copyout(req.out_param, r->out_param, req.out_param_len); diag_done: if(req.in_param) free(req.in_param, M_DEVBUF); if(req.out_param) free(req.out_param, M_DEVBUF); break; } /* default */ default: error = ENOTTY; break; } return(error); }
/*---------------------------------------------------------------------------* * link a driver(unit) to a B-channel(controller,unit,channel) *---------------------------------------------------------------------------*/ static int i4b_link_bchandrvr(call_desc_t *cd) { int t = ctrl_desc[cd->controller].ctrl_type; if(t < 0 || t >= CTRL_NUMTYPES || ctrl_types[t].get_linktab == NULL) { cd->ilt = NULL; } else { cd->ilt = ctrl_types[t].get_linktab( ctrl_desc[cd->controller].unit, cd->channelid); } switch(cd->driver) { #if NI4BRBCH > 0 case BDRV_RBCH: cd->dlt = rbch_ret_linktab(cd->driver_unit); break; #endif #if NI4BTEL > 0 case BDRV_TEL: cd->dlt = tel_ret_linktab(cd->driver_unit); break; #endif #if NI4BIPR > 0 case BDRV_IPR: cd->dlt = ipr_ret_linktab(cd->driver_unit); break; #endif #if NI4BISPPP > 0 case BDRV_ISPPP: cd->dlt = i4bisppp_ret_linktab(cd->driver_unit); break; #endif #if NI4BING > 0 case BDRV_ING: cd->dlt = ing_ret_linktab(cd->driver_unit); break; #endif default: cd->dlt = NULL; break; } if(cd->dlt == NULL || cd->ilt == NULL) return(-1); if(t >= 0 && t < CTRL_NUMTYPES && ctrl_types[t].set_linktab != NULL) { ctrl_types[t].set_linktab( ctrl_desc[cd->controller].unit, cd->channelid, cd->dlt); } switch(cd->driver) { #if NI4BRBCH > 0 case BDRV_RBCH: rbch_set_linktab(cd->driver_unit, cd->ilt); break; #endif #if NI4BTEL > 0 case BDRV_TEL: tel_set_linktab(cd->driver_unit, cd->ilt); break; #endif #if NI4BIPR > 0 case BDRV_IPR: ipr_set_linktab(cd->driver_unit, cd->ilt); break; #endif #if NI4BISPPP > 0 case BDRV_ISPPP: i4bisppp_set_linktab(cd->driver_unit, cd->ilt); break; #endif #if NI4BING > 0 case BDRV_ING: ing_set_linktab(cd->driver_unit, cd->ilt); break; #endif default: return(0); break; } /* activate B channel */ (*cd->ilt->bch_config)(cd->ilt->unit, cd->ilt->channel, cd->bprot, 1); return(0); }