1/* 2 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 * 25 *--------------------------------------------------------------------------- 26 * 27 * i4b_l4if.c - Layer 3 interface to Layer 4 28 * ------------------------------------------- 29 * 30 * $Id: i4b_l4if.c,v 1.19 2005/12/11 12:25:06 christos Exp $ 31 * 32 * $FreeBSD$ 33 * 34 * last edit-date: [Fri Jan 5 11:33:47 2001] 35 * 36 *---------------------------------------------------------------------------*/ 37 38#include <sys/cdefs.h> 39__KERNEL_RCSID(0, "$NetBSD: i4b_l4if.c,v 1.14.2.4 2005/03/04 16:53:45 skrll Exp $"); 40 41#ifdef __FreeBSD__ 42#include "i4bq931.h" 43#else 44#define NI4BQ931 1 45#endif 46#if NI4BQ931 > 0 47 48#include <sys/param.h> 49#include <sys/kernel.h> 50#include <sys/systm.h> 51#include <sys/mbuf.h> 52#include <sys/socket.h> 53#include <net/if.h> 54 55#if defined(__NetBSD__) && __NetBSD_Version__ >= 104230000 56#include <sys/callout.h> 57#endif 58 59#ifdef __FreeBSD__ 60#include <machine/i4b_debug.h> 61#include <machine/i4b_ioctl.h> 62#include <machine/i4b_cause.h> 63#else 64#include <netisdn/i4b_debug.h> 65#include <netisdn/i4b_ioctl.h> 66#include <netisdn/i4b_cause.h> 67#endif 68 69#include <netisdn/i4b_isdnq931.h> 70#include <netisdn/i4b_l2.h> 71#include <netisdn/i4b_l1l2.h> 72#include <netisdn/i4b_l3l4.h> 73#include <netisdn/i4b_mbuf.h> 74#include <netisdn/i4b_global.h> 75 76#include <netisdn/i4b_l3.h> 77#include <netisdn/i4b_l3fsm.h> 78#include <netisdn/i4b_q931.h> 79 80#include <netisdn/i4b_l4.h> 81 82void n_connect_request(struct call_desc *cd); 83void n_connect_response(struct call_desc *cd, int response, int cause); 84void n_disconnect_request(struct call_desc *cd, int cause); 85void n_alert_request(struct call_desc *cd); 86void n_mgmt_command(struct isdn_l3_driver *drv, int cmd, void *parm); 87 88/*---------------------------------------------------------------------------* 89 * i4b_mdl_status_ind - status indication from lower layers 90 *---------------------------------------------------------------------------*/ 91int 92i4b_mdl_status_ind(struct isdn_l3_driver *d, int status, int parm) 93{ 94 int sendup, update_leds = 0; 95 int i; 96 97 NDBGL3(L3_MSG, "isdnif = %d, status = %d, parm = %d", 98 d->isdnif, status, parm); 99 100 switch(status) 101 { 102 case STI_ATTACH: 103 if (parm) { 104 NDBGL3(L3_MSG, "STI_ATTACH: attaching isdnif %d", d->isdnif); 105 } else { 106 NDBGL3(L3_MSG, "STI_ATTACH: dettaching isdnif %d", d->isdnif); 107 } 108 break; 109 110 case STI_L1STAT: 111 i4b_l4_l12stat(d, 1, parm); 112 update_leds = 1; 113 NDBGL3(L3_MSG, "STI_L1STAT: isdnif %d layer 1 = %s", d->isdnif, status ? "up" : "down"); 114 break; 115 116 case STI_L2STAT: 117 i4b_l4_l12stat(d, 2, parm); 118 update_leds = 1; 119 NDBGL3(L3_MSG, "STI_L2STAT: isdnif %d layer 2 = %s", d->isdnif, status ? "up" : "down"); 120 break; 121 122 case STI_TEIASG: 123 d->tei = parm; 124 i4b_l4_teiasg(d, parm); 125 update_leds = 1; 126 NDBGL3(L3_MSG, "STI_TEIASG: isdnif %d TEI = %d = 0x%02x", d->isdnif, parm, parm); 127 break; 128 129 case STI_PDEACT: /* L1 T4 timeout */ 130 NDBGL3(L3_ERR, "STI_PDEACT: isdnif %d TEI = %d = 0x%02x", d->isdnif, parm, parm); 131 132 update_leds = 1; 133 sendup = 0; 134 135 for(i=0; i < num_call_desc; i++) 136 { 137 if(call_desc[i].isdnif == d->isdnif) 138 { 139 i4b_l3_stop_all_timers(&(call_desc[i])); 140 if(call_desc[i].cdid != CDID_UNUSED) { 141 sendup++; 142 call_desc[i].cdid = CDID_UNUSED; 143 } 144 } 145 } 146 147 d->dl_est = DL_DOWN; 148 149 for (i = 0; i < d->nbch; i++) 150 d->bch_state[i] = BCH_ST_FREE; 151 d->tei = -1; 152 153 if(sendup) 154 { 155 i4b_l4_pdeact(d, sendup); 156 } 157 break; 158 159 case STI_NOL1ACC: /* no outgoing access to S0 */ 160 NDBGL3(L3_ERR, "STI_NOL1ACC: isdnif %d no outgoing access to S0", d->isdnif); 161 update_leds = 1; 162 163 for(i=0; i < num_call_desc; i++) 164 { 165 if(call_desc[i].isdnif == d->isdnif) 166 { 167 if(call_desc[i].cdid != CDID_UNUSED) 168 { 169 SET_CAUSE_TYPE(call_desc[i].cause_in, CAUSET_I4B); 170 SET_CAUSE_VAL(call_desc[i].cause_in, CAUSE_I4B_L1ERROR); 171 i4b_l4_disconnect_ind(&(call_desc[i])); 172 } 173 } 174 } 175 d->dl_est = DL_DOWN; 176 177 for (i = 0; i < d->nbch; i++) 178 d->bch_state[i] = BCH_ST_FREE; 179 d->tei = -1; 180 181 break; 182 183 default: 184 NDBGL3(L3_ERR, "ERROR, isdnif %d, unknown status value %d!", d->isdnif, status); 185 break; 186 } 187 188 if (update_leds && d != NULL) 189 update_controller_leds(d); 190 191 return(0); 192} 193 194void 195update_controller_leds(struct isdn_l3_driver *d) 196{ 197 intptr_t leds = 0; 198 199 if (d->tei != -1) 200 leds |= CMRLEDS_TEI; 201 if (d->bch_state[CHAN_B1] != BCH_ST_FREE) 202 leds |= CMRLEDS_B0; 203 if (d->bch_state[CHAN_B2] != BCH_ST_FREE) 204 leds |= CMRLEDS_B1; 205 206 d->l3driver->N_MGMT_COMMAND(d, CMR_SETLEDS, (void*)leds); 207} 208 209/*---------------------------------------------------------------------------* 210 * send command to the lower layers 211 *---------------------------------------------------------------------------*/ 212void 213n_mgmt_command(struct isdn_l3_driver *d, int cmd, void *parm) 214{ 215 int i; 216 217 switch(cmd) 218 { 219 case CMR_DOPEN: 220 NDBGL3(L3_MSG, "CMR_DOPEN for isdnif %d", d->isdnif); 221 222 for(i=0; i < num_call_desc; i++) 223 { 224 if(call_desc[i].isdnif == d->isdnif) 225 { 226 call_desc[i].cdid = CDID_UNUSED; 227 } 228 } 229 d->dl_est = DL_DOWN; 230 for (i = 0; i < d->nbch; i++) 231 d->bch_state[i] = BCH_ST_FREE; 232 d->tei = -1; 233 234 break; 235 236 case CMR_DCLOSE: 237 NDBGL3(L3_MSG, "CMR_DCLOSE for isdnif %d", d->isdnif); 238 break; 239 240 default: 241 NDBGL3(L3_MSG, "unknown cmd %d for isdnif %d", 242 cmd, d->isdnif); 243 break; 244 } 245 246 i4b_mdl_command_req(d, cmd, parm); 247} 248 249/*---------------------------------------------------------------------------* 250 * handle connect request message from userland 251 *---------------------------------------------------------------------------*/ 252void 253n_connect_request(struct call_desc *cd) 254{ 255 next_l3state(cd, EV_SETUPRQ); 256} 257 258/*---------------------------------------------------------------------------* 259 * handle setup response message from userland 260 *---------------------------------------------------------------------------*/ 261void 262n_connect_response(struct call_desc *cd, int response, int cause) 263{ 264 struct isdn_l3_driver *d = cd->l3drv; 265 int chstate; 266 267 T400_stop(cd); 268 269 cd->response = response; 270 cd->cause_out = cause; 271 272 switch(response) 273 { 274 case SETUP_RESP_ACCEPT: 275 next_l3state(cd, EV_SETACRS); 276 chstate = BCH_ST_USED; 277 break; 278 279 case SETUP_RESP_REJECT: 280 next_l3state(cd, EV_SETRJRS); 281 chstate = BCH_ST_FREE; 282 break; 283 284 case SETUP_RESP_DNTCRE: 285 next_l3state(cd, EV_SETDCRS); 286 chstate = BCH_ST_FREE; 287 break; 288 289 default: /* failsafe */ 290 next_l3state(cd, EV_SETDCRS); 291 chstate = BCH_ST_FREE; 292 NDBGL3(L3_ERR, "unknown response, doing SETUP_RESP_DNTCRE"); 293 break; 294 } 295 296 if((cd->channelid >= 0) && (cd->channelid < d->nbch)) 297 { 298 d->bch_state[cd->channelid] = chstate; 299 /* 300 * XXX: don't call l2 function for active cards 301 */ 302 if (d->l3driver->N_DOWNLOAD == NULL) 303 i4b_l2_channel_set_state(cd->l3drv, 304 cd->channelid, chstate); 305 update_controller_leds(d); 306 } 307 else 308 { 309 NDBGL3(L3_MSG, "Warning, invalid channelid %d, response = %d\n", cd->channelid, response); 310 } 311} 312 313/*---------------------------------------------------------------------------* 314 * handle disconnect request message from userland 315 *---------------------------------------------------------------------------*/ 316void 317n_disconnect_request(struct call_desc *cd, int cause) 318{ 319 cd->cause_out = cause; 320 321 next_l3state(cd, EV_DISCRQ); 322} 323 324/*---------------------------------------------------------------------------* 325 * handle alert request message from userland 326 *---------------------------------------------------------------------------*/ 327void 328n_alert_request(struct call_desc *cd) 329{ 330 next_l3state(cd, EV_ALERTRQ); 331} 332 333#endif /* NI4BQ931 > 0 */ 334