File:  [DragonFly] / src / sys / net / i4b / capi / capi_l4if.c
Revision 1.4: download - view: text, annotated - select for diffs
Thu Aug 7 21:54:30 2003 UTC (11 years, 4 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
kernel tree reorganization stage 1: Major cvs repository work (not logged as
commits) plus a major reworking of the #include's to accomodate the
relocations.

    * CVS repository files manually moved.  Old directories left intact
      and empty (temporary).

    * Reorganize all filesystems into vfs/, most devices into dev/,
      sub-divide devices by function.

    * Begin to move device-specific architecture files to the device
      subdirs rather then throwing them all into, e.g. i386/include

    * Reorganize files related to system busses, placing the related code
      in a new bus/ directory.  Also move cam to bus/cam though this may
      not have been the best idea in retrospect.

    * Reorganize emulation code and place it in a new emulation/ directory.

    * Remove the -I- compiler option in order to allow #include file
      localization, rename all config generated X.h files to use_X.h to
      clean up the conflicts.

    * Remove /usr/src/include (or /usr/include) dependancies during the
      kernel build, beyond what is normally needed to compile helper
      programs.

    * Make config create 'machine' softlinks for architecture specific
      directories outside of the standard <arch>/include.

    * Bump the config rev.

    WARNING! after this commit /usr/include and /usr/src/sys/compile/*
    should be regenerated from scratch.

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