File:  [DragonFly] / src / sys / net / i4b / capi / capi_l4if.c
Revision 1.5: download - view: text, annotated - select for diffs
Fri Apr 16 15:40:20 2004 UTC (10 years, 7 months ago) by joerg
Branches: MAIN
CVS tags: HEAD, DragonFly_Snap29Sep2004, DragonFly_Snap13Sep2004, DragonFly_1_0_REL, DragonFly_1_0_RC1, DragonFly_1_0A_REL
Merge changes from FreeBSD 5:
- remove dependency on device counting
- undo massive inlining on iavc

    1: /*
    2:  * Copyright (c) 2001 Cubical Solutions Ltd. 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:  * capi/capi_l4if.c	The CAPI i4b L4/device interface.
   26:  *
   27:  * $FreeBSD: src/sys/i4b/capi/capi_l4if.c,v 1.1.2.1 2001/08/10 14:08:34 obrien Exp $
   28:  * $DragonFly: src/sys/net/i4b/capi/capi_l4if.c,v 1.5 2004/04/16 15:40:20 joerg Exp $
   29:  */
   30: 
   31: #include <sys/param.h>
   32: #include <sys/kernel.h>
   33: #include <sys/systm.h>
   34: #include <sys/mbuf.h>
   35: #include <sys/socket.h>
   36: #include <net/if.h>
   37: 
   38: #include <net/i4b/include/machine/i4b_debug.h>
   39: #include <net/i4b/include/machine/i4b_ioctl.h>
   40: #include <net/i4b/include/machine/i4b_cause.h>
   41: 
   42: #include "../include/i4b_l3l4.h"
   43: #include "../include/i4b_mbuf.h"
   44: #include "../include/i4b_global.h"
   45: #include "../layer4/i4b_l4.h"
   46: 
   47: #include "capi.h"
   48: #include "capi_msgs.h"
   49: 
   50: static void n_connect_request(u_int cdid);
   51: static void n_connect_response(u_int cdid, int response, int cause);
   52: static void n_disconnect_request(u_int cdid, int cause);
   53: static void n_alert_request(u_int cdid);
   54: static void n_mgmt_command(int unit, int cmd, void *parm);
   55: static int  n_download(int unit, int, struct isdn_dr_prot *);
   56: 
   57: capi_softc_t *capi_sc[MAX_CONTROLLERS] = { NULL, };
   58: int ncapi = 0;
   59: 
   60: /*
   61: //  i4b_capi_{ret,set}_linktab
   62: //      i4b driver glue.
   63: //
   64: //  i4b_capi_bch_config
   65: //      Called by i4b driver to flush + {en,dis}able a channel.
   66: //
   67: //  i4b_capi_bch_start_tx
   68: //      Called by i4b driver to transmit a queued mbuf.
   69: //
   70: //  i4b_capi_bch_stat
   71: //      Called by i4b driver to obtain statistics information.
   72: */
   73: 
   74: static isdn_link_t *
   75: i4b_capi_ret_linktab(int unit, int channel)
   76: {
   77:     capi_softc_t *sc = capi_sc[unit];
   78:     return &sc->sc_bchan[channel].capi_isdn_linktab;
   79: }
   80: 
   81: static void
   82: i4b_capi_set_linktab(int unit, int channel, drvr_link_t *dlt)
   83: {
   84:     capi_softc_t *sc = capi_sc[unit];
   85:     sc->sc_bchan[channel].capi_drvr_linktab = dlt;
   86: }
   87: 
   88: static void
   89: i4b_capi_bch_config(int unit, int chan, int bprot, int activate)
   90: {
   91:     capi_softc_t *sc = capi_sc[unit];
   92: 
   93:     i4b_Bcleanifq(&sc->sc_bchan[chan].tx_queue);
   94:     sc->sc_bchan[chan].tx_queue.ifq_maxlen = IFQ_MAXLEN;
   95:     sc->sc_bchan[chan].txcount = 0;
   96: 
   97:     /* The telephony drivers use rx_queue for receive. */
   98: 
   99:     i4b_Bcleanifq(&sc->sc_bchan[chan].rx_queue);
  100:     sc->sc_bchan[chan].rx_queue.ifq_maxlen = IFQ_MAXLEN;
  101:     sc->sc_bchan[chan].rxcount = 0;
  102: 
  103:     /* HDLC frames are put to in_mbuf */
  104: 
  105:     i4b_Bfreembuf(sc->sc_bchan[chan].in_mbuf);
  106:     sc->sc_bchan[chan].in_mbuf = NULL;
  107: 
  108:     /* Because of the difference, we need to remember the protocol. */
  109: 
  110:     sc->sc_bchan[chan].bprot = bprot;
  111:     sc->sc_bchan[chan].busy = 0;
  112: }
  113: 
  114: static void
  115: i4b_capi_bch_start_tx(int unit, int chan)
  116: {
  117:     capi_softc_t *sc = capi_sc[unit];
  118:     int s;
  119: 
  120:     s = SPLI4B();
  121: 
  122:     if (sc->sc_bchan[chan].state != B_CONNECTED) {
  123: 	splx(s);
  124: 	printf("capi%d: start_tx on unconnected channel\n", sc->sc_unit);
  125: 	return;
  126:     }
  127: 
  128:     if (sc->sc_bchan[chan].busy) {
  129: 	splx(s);
  130: 	return;
  131:     }
  132: 
  133:     capi_start_tx(sc, chan);
  134: 
  135:     splx(s);
  136: }
  137: 
  138: static void
  139: i4b_capi_bch_stat(int unit, int chan, bchan_statistics_t *bsp)
  140: {
  141:     capi_softc_t *sc = capi_sc[unit];
  142:     int s = SPLI4B();
  143: 
  144:     bsp->outbytes = sc->sc_bchan[chan].txcount;
  145:     bsp->inbytes = sc->sc_bchan[chan].rxcount;
  146: 
  147:     sc->sc_bchan[chan].txcount = 0;
  148:     sc->sc_bchan[chan].rxcount = 0;
  149: 
  150:     splx(s);
  151: }
  152: 
  153: int capi_start_tx(capi_softc_t *sc, int chan)
  154: {
  155:     struct mbuf *m_b3;
  156:     int sent = 0;
  157: 
  158:     _IF_DEQUEUE(&sc->sc_bchan[chan].tx_queue, m_b3);
  159:     while (m_b3) {
  160: 	struct mbuf *m = m_b3->m_next;
  161: 
  162: 	sc->sc_bchan[chan].txcount += m_b3->m_len;
  163: 	capi_data_b3_req(sc, chan, m_b3);
  164: 	sent++;
  165: 
  166: 	m_b3 = m;
  167:     }
  168: 
  169:     if (sc->sc_bchan[chan].capi_drvr_linktab) {
  170: 	/* Notify i4b driver of activity, and if the queue is drained. */
  171: 
  172: 	if (sent)
  173: 	    (*sc->sc_bchan[chan].capi_drvr_linktab->bch_activity)(
  174: 		sc->sc_bchan[chan].capi_drvr_linktab->unit, ACT_TX);
  175: 
  176: 	if (IF_QEMPTY(&sc->sc_bchan[chan].tx_queue))
  177: 	    (*sc->sc_bchan[chan].capi_drvr_linktab->bch_tx_queue_empty)(
  178: 		sc->sc_bchan[chan].capi_drvr_linktab->unit);
  179:     }
  180: 
  181:     return sent;
  182: }
  183: 
  184: /*
  185: //  capi_ll_attach
  186: //      Called by a link layer driver at boot time.
  187: */
  188: 
  189: int
  190: capi_ll_attach(capi_softc_t *sc)
  191: {
  192:     int i;
  193: 
  194:     if (ncapi == (sizeof(capi_sc) / sizeof(capi_sc[0]))) {
  195: 	printf("capi%d: too many units, increase MAX_CONTROLLERS\n", ncapi);
  196: 	return (ENXIO);
  197:     }
  198: 
  199:     /* Unit type and subtype; sc is partly filled by ll driver */
  200:     
  201:     ctrl_desc[nctrl].unit = ncapi;
  202:     ctrl_desc[nctrl].ctrl_type = CTRL_CAPI;
  203:     ctrl_desc[nctrl].card_type = sc->card_type;
  204: 
  205:     /* L4 callbacks */
  206:     
  207:     ctrl_types[CTRL_CAPI].get_linktab = i4b_capi_ret_linktab;
  208:     ctrl_types[CTRL_CAPI].set_linktab = i4b_capi_set_linktab;
  209: 
  210:     ctrl_desc[nctrl].N_CONNECT_REQUEST = n_connect_request;
  211:     ctrl_desc[nctrl].N_CONNECT_RESPONSE = n_connect_response;
  212:     ctrl_desc[nctrl].N_DISCONNECT_REQUEST = n_disconnect_request;
  213:     ctrl_desc[nctrl].N_ALERT_REQUEST = n_alert_request;
  214:     ctrl_desc[nctrl].N_DOWNLOAD = n_download;
  215:     ctrl_desc[nctrl].N_DIAGNOSTICS = NULL; /* XXX todo */
  216:     ctrl_desc[nctrl].N_MGMT_COMMAND = n_mgmt_command;
  217: 
  218:     /* Unit state */
  219: 
  220:     sc->sc_enabled = FALSE;
  221:     sc->sc_state = C_DOWN;
  222:     sc->sc_msgid = 0;
  223: 
  224:     ctrl_desc[nctrl].dl_est = DL_DOWN;
  225:     ctrl_desc[nctrl].nbch = sc->sc_nbch;
  226: 
  227:     for (i = 0; i < sc->sc_nbch; i++) {
  228: 	ctrl_desc[nctrl].bch_state[i] = BCH_ST_FREE;
  229: 	sc->sc_bchan[i].ncci = INVALID;
  230: 	sc->sc_bchan[i].msgid = 0;
  231: 	sc->sc_bchan[i].busy = 0;
  232: 	sc->sc_bchan[i].state = B_FREE;
  233: 
  234: 	memset(&sc->sc_bchan[i].tx_queue, 0, sizeof(struct ifqueue));
  235: 	memset(&sc->sc_bchan[i].rx_queue, 0, sizeof(struct ifqueue));
  236: 	sc->sc_bchan[i].tx_queue.ifq_maxlen = IFQ_MAXLEN;
  237: 	sc->sc_bchan[i].rx_queue.ifq_maxlen = IFQ_MAXLEN;
  238: 
  239: #if defined (__FreeBSD__) && __FreeBSD__ > 4
  240: 	mtx_init(&sc->sc_bchan[i].tx_queue.ifq_mtx, "i4b_capi_tx", MTX_DEF);
  241: 	mtx_init(&sc->sc_bchan[i].rx_queue.ifq_mtx, "i4b_capi_rx", MTX_DEF);	
  242: #endif    
  243: 
  244: 	sc->sc_bchan[i].txcount = 0;
  245: 	sc->sc_bchan[i].rxcount = 0;
  246: 
  247: 	sc->sc_bchan[i].cdid = CDID_UNUSED;
  248: 	sc->sc_bchan[i].bprot = BPROT_NONE;
  249: 	sc->sc_bchan[i].in_mbuf = NULL;
  250: 
  251: 	sc->sc_bchan[i].capi_drvr_linktab = NULL;
  252: 
  253: 	sc->sc_bchan[i].capi_isdn_linktab.unit = ncapi;
  254: 	sc->sc_bchan[i].capi_isdn_linktab.channel = i;
  255: 	sc->sc_bchan[i].capi_isdn_linktab.bch_config = i4b_capi_bch_config;
  256: 	sc->sc_bchan[i].capi_isdn_linktab.bch_tx_start = i4b_capi_bch_start_tx;
  257: 	sc->sc_bchan[i].capi_isdn_linktab.bch_stat = i4b_capi_bch_stat;
  258: 	sc->sc_bchan[i].capi_isdn_linktab.tx_queue = &sc->sc_bchan[i].tx_queue;
  259: 	sc->sc_bchan[i].capi_isdn_linktab.rx_queue = &sc->sc_bchan[i].rx_queue;
  260: 	sc->sc_bchan[i].capi_isdn_linktab.rx_mbuf = &sc->sc_bchan[i].in_mbuf;
  261:     }
  262: 
  263:     ctrl_desc[nctrl].tei = -1;
  264: 
  265:     /* Up the controller index and store the softc */
  266: 
  267:     sc->sc_unit = ncapi;
  268:     capi_sc[ncapi++] = sc;
  269:     sc->ctrl_unit = nctrl++;
  270: 
  271:     printf("capi%d: card type %d attached\n", sc->sc_unit, sc->card_type);
  272: 
  273:     return(0);
  274: }
  275: 
  276: /*
  277: //  n_mgmt_command
  278: //      i4b L4 management command.
  279: */
  280: 
  281: static void
  282: n_mgmt_command(int unit, int op, void *arg)
  283: {
  284:     capi_softc_t *sc = capi_sc[unit];
  285: 
  286:     printf("capi%d: mgmt command %d\n", sc->sc_unit, op);
  287: 
  288:     switch(op) {
  289:     case CMR_DOPEN:
  290: 	sc->sc_enabled = TRUE;
  291: 	break;
  292: 
  293:     case CMR_DCLOSE:
  294: 	sc->sc_enabled = FALSE;
  295: 	break;
  296: 
  297:     case CMR_SETTRACE:
  298: 	break;
  299: 
  300:     default:
  301: 	break;
  302:     }
  303: }
  304: 
  305: /*
  306: //  n_connect_request
  307: //      i4b L4 wants to connect. We assign a B channel to the call,
  308: //      send a CAPI_CONNECT_REQ, and set the channel to B_CONNECT_CONF.
  309: */
  310: 
  311: static void
  312: n_connect_request(u_int cdid)
  313: {
  314:     call_desc_t *cd = cd_by_cdid(cdid);
  315:     capi_softc_t *sc;
  316:     int bch, s;
  317: 
  318:     if (!cd) {
  319: 	printf("capi?: invalid cdid %d\n", cdid);
  320: 	return;
  321:     }
  322: 
  323:     sc = capi_sc[ctrl_desc[cd->controller].unit];
  324:     bch = cd->channelid;
  325: 
  326:     s = SPLI4B();
  327: 
  328:     if ((bch < 0) || (bch >= sc->sc_nbch))
  329: 	for (bch = 0; bch < sc->sc_nbch; bch++)
  330: 	    if (sc->sc_bchan[bch].state == B_FREE)
  331: 		break;
  332: 
  333:     if (bch == sc->sc_nbch) {
  334: 	splx(s);
  335: 	printf("capi%d: no free B channel\n", sc->sc_unit);
  336: 	return;
  337:     }
  338: 
  339:     cd->channelid = bch;
  340: 
  341:     capi_connect_req(sc, cd);
  342:     splx(s);
  343: }
  344: 
  345: /*
  346: //  n_connect_response
  347: //      i4b L4 answers a call. We send a CONNECT_RESP with the proper
  348: //      Reject code, and set the channel to B_CONNECT_B3_IND or B_FREE,
  349: //      depending whether we answer or not.
  350: */
  351: 
  352: static void
  353: n_connect_response(u_int cdid, int response, int cause)
  354: {
  355:     call_desc_t *cd = cd_by_cdid(cdid);
  356:     capi_softc_t *sc;
  357:     int bch, s;
  358: 
  359:     if (!cd) {
  360: 	printf("capi?: invalid cdid %d\n", cdid);
  361: 	return;
  362:     }
  363: 
  364:     sc = capi_sc[ctrl_desc[cd->controller].unit];
  365:     bch = cd->channelid;
  366: 
  367:     T400_stop(cd);
  368: 	
  369:     cd->response = response;
  370:     cd->cause_out = cause;
  371: 
  372:     s = SPLI4B();
  373:     capi_connect_resp(sc, cd);
  374:     splx(s);
  375: }
  376: 
  377: /*
  378: //  n_disconnect_request
  379: //      i4b L4 wants to disconnect. We send a DISCONNECT_REQ and
  380: //      set the channel to B_DISCONNECT_CONF.
  381: */
  382: 
  383: static void
  384: n_disconnect_request(u_int cdid, int cause)
  385: {
  386:     call_desc_t *cd = cd_by_cdid(cdid);
  387:     capi_softc_t *sc;
  388:     int bch, s;
  389: 
  390:     if (!cd) {
  391: 	printf("capi?: invalid cdid %d\n", cdid);
  392: 	return;
  393:     }
  394: 
  395:     sc = capi_sc[ctrl_desc[cd->controller].unit];
  396:     bch = cd->channelid;
  397: 
  398:     cd->cause_out = cause;
  399: 
  400:     s = SPLI4B();
  401:     capi_disconnect_req(sc, cd);
  402:     splx(s);
  403: }
  404: 
  405: /*
  406: //  n_alert_request
  407: //      i4b L4 wants to alert an incoming call. We send ALERT_REQ.
  408: */
  409: 
  410: static void
  411: n_alert_request(u_int cdid)
  412: {
  413:     call_desc_t *cd = cd_by_cdid(cdid);
  414:     capi_softc_t *sc;
  415:     int s;
  416: 
  417:     if (!cd) {
  418: 	printf("capi?: invalid cdid %d\n", cdid);
  419: 	return;
  420:     }
  421: 
  422:     sc = capi_sc[ctrl_desc[cd->controller].unit];
  423: 
  424:     s = SPLI4B();
  425:     capi_alert_req(sc, cd);
  426:     splx(s);
  427: }
  428: 
  429: /*
  430: //  n_download
  431: //      L4 -> firmware download
  432: */
  433: 
  434: static int
  435: n_download(int unit, int numprotos, struct isdn_dr_prot *protocols)
  436: {
  437:     capi_softc_t *sc = capi_sc[unit];
  438: 
  439:     if (sc->load) {
  440: 	(*capi_sc[unit]->load)(sc, protocols[0].bytecount,
  441: 			       protocols[0].microcode);
  442:     }
  443: 
  444:     return(0);
  445: }