The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/daic.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2002 The NetBSD Foundation, Inc.
    3  * All rights reserved.
    4  *
    5  * This code is derived from software contributed to The NetBSD Foundation
    6  * by Martin Husemann <martin@NetBSD.org>.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *        This product includes software developed by the NetBSD
   19  *        Foundation, Inc. and its contributors.
   20  * 4. Neither the name of The NetBSD Foundation nor the names of its
   21  *    contributors may be used to endorse or promote products derived
   22  *    from this software without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   27  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   28  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   34  * POSSIBILITY OF SUCH DAMAGE.
   35  *
   36  */
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: daic.c,v 1.22 2005/02/27 00:27:01 perry Exp $");
   40 
   41 /*
   42  * daic.c: MI driver for Diehl active ISDN cards (S, SX, SXn, SCOM, QUADRO)
   43  */
   44 
   45 #include <sys/param.h>
   46 #include <sys/systm.h>
   47 #include <sys/kernel.h>
   48 #include <sys/errno.h>
   49 #include <sys/ioctl.h>
   50 #include <sys/device.h>
   51 #include <sys/malloc.h>
   52 #include <sys/proc.h>
   53 #include <sys/socket.h>
   54 #include <net/if.h>
   55 
   56 #include <netisdn/i4b_ioctl.h>
   57 #include <netisdn/i4b_l3l4.h>
   58 #include <netisdn/i4b_isdnq931.h>
   59 #include <netisdn/i4b_q931.h>
   60 #include <netisdn/i4b_l3fsm.h>
   61 #include <netisdn/i4b_l4.h>
   62 
   63 #include <machine/bus.h>
   64 #include <dev/ic/daicvar.h>
   65 #include <dev/ic/daicreg.h>
   66 #include <dev/microcode/daic/dnload.h>
   67 
   68 #ifdef NetBSD1_3
   69 #if NetBSD1_3 < 2
   70 /* the device is MI, only the attach struct is in the bus
   71    dependent frontend. And only on old versions... */
   72 struct cfdriver daic_cd = {
   73         NULL, "daic", DV_DULL
   74 };
   75 #endif
   76 #endif
   77 
   78 /* local function prototypes */
   79 static char * cardtypename(int cardtype);
   80 static int daic_download(void *, int portcount, struct isdn_dr_prot *data);
   81 static int daic_diagnostic(void *, struct isdn_diagnostic_request *req);
   82 static void daic_connect_request(struct call_desc *cd);
   83 static void daic_connect_response(struct call_desc *cd, int, int);
   84 static void daic_disconnect_request(struct call_desc *cd, int);
   85 static int daic_reset(bus_space_tag_t bus, bus_space_handle_t io, int port, int *memsize);
   86 static int daic_handle_intr(struct daic_softc *sc, int port);
   87 static void daic_register_port(struct daic_softc *sc, int port);
   88 static void daic_request(struct daic_softc *sc, int port, u_int req, u_int id, bus_size_t parmsize, const u_int8_t *parms);
   89 static u_int daic_assign(struct daic_softc *sc, int port, u_int instance, bus_size_t parmsize, const u_int8_t *parms);
   90 static void daic_indicate_ind(struct daic_softc *sc, int port);
   91 static void daic_bch_config(void *, int channel, int bprot, int updown);
   92 static void daic_bch_tx_start(void *, int channel);
   93 static void daic_set_link(void *softc, int channel,
   94         const struct isdn_l4_driver_functions *l4_driver, void *l4_inst );
   95 static void daic_mgmt_command(struct isdn_l3_driver *drv, int cmd, void *parm);
   96 static void daic_alert_request(struct call_desc *cd);
   97 
   98 static isdn_link_t *daic_ret_linktab(void *softc, int channel);
   99 
  100 #ifdef DAIC_DEBUG
  101 static void daic_dump_request(struct daic_softc *sc, int port, u_int req, u_int id, bus_size_t parmsize, u_int8_t *parms);
  102 #endif
  103 
  104 /* static data */
  105 static char *cardnames[] = {
  106         "S", "SX", "SCOM", "QUADRO"
  107 };
  108 
  109 static char *err_codes[DAIC_RC_ERRMASK+1] = {
  110         "NO ERROR",
  111         "UNKNOWN COMMAND",
  112         "WRONG COMMAND",
  113         "WRONG ID",
  114         "WRONG CH",
  115         "UNKNOWN IE",
  116         "WRONG IE",
  117         "OUT OF RESOURCES"
  118 };
  119 
  120 /* fixed parameters */
  121 
  122 /* no parameters */
  123 static u_int8_t parm_none[] = { 0 };
  124 #define VOIDREQ(sc,port,req,id) daic_request(sc, port, req, id, sizeof parm_none, parm_none)
  125 
  126 /* assign request for the global d-channel instance */
  127 static u_int8_t parm_global_assign[] = {
  128 /*      BC      len     cap     rate    A-law   */
  129         0x04,   0x03,   0x80,   0x90,   0xa3,   /* 64k speech */
  130         0x04,   0x02,   0x88,   0x90,           /* 64k data */
  131         0x04,   0x03,   0x89,   0x90,   0xa3,   /* restricted digital info */
  132         0x04,   0x03,   0x90,   0x90,   0xa3,   /* 3.1k speech */
  133 /*      shift6  SIN     len     service         */
  134         0x96,   0x01,   0x02,   0x00, 0x00,     /* any service */
  135 /*      end of parms */
  136         0x00
  137 };
  138 
  139 /*---------------------------------------------------------------------------*
  140  *      Return the name of a card with given cardtype
  141  *---------------------------------------------------------------------------*/
  142 static char *
  143 cardtypename(cardtype)
  144         int cardtype;
  145 {
  146         if (cardtype >= 0 && cardtype < (sizeof(cardnames) / sizeof(cardnames[0])))
  147                 return cardnames[cardtype];
  148         else
  149                 return "unknown type";
  150 }
  151 
  152 /*---------------------------------------------------------------------------*
  153  * Probe for presence of device at given io space.
  154  * Return the card type (stupid ISA needs to know this in advance, to
  155  * calculate the share memory size).
  156  *---------------------------------------------------------------------------*/
  157 int
  158 daic_probe(bus, io)
  159         bus_space_tag_t bus;
  160         bus_space_handle_t io;
  161 {
  162         return (daic_reset(bus, io, 0, NULL));
  163 }
  164 
  165 /*---------------------------------------------------------------------------*
  166  * Attach and initialize the card at given io space.
  167  *---------------------------------------------------------------------------*/
  168 void
  169 daic_attach(self, sc)
  170         struct device *self;
  171         struct daic_softc *sc;
  172 {
  173         int i, num_ports, memsize = 0;
  174 
  175         /* init sc */
  176         memset(sc->sc_port, 0, sizeof sc->sc_port);
  177         memset(sc->sc_con, 0, sizeof sc->sc_con);
  178         sc->sc_cardtype = -1;
  179 
  180         /* init card */
  181         sc->sc_cardtype = daic_reset(sc->sc_iot, sc->sc_ioh, 0, &memsize);
  182         if (sc->sc_cardtype == 0) {
  183                 printf(": unknown card, can not attach.\n");
  184                 return;
  185         }
  186 
  187         printf("\n");
  188         printf("%s: EICON.Diehl %s\n", sc->sc_dev.dv_xname,
  189             cardtypename(sc->sc_cardtype));
  190         printf("%s: %d kByte on board RAM\n", sc->sc_dev.dv_xname, memsize);
  191         num_ports = sc->sc_cardtype == DAIC_TYPE_QUAD ? 4 : 1;
  192         for (i = 0; i < num_ports; i++)
  193                 sc->sc_port[i].du_state = DAIC_STATE_DOWNLOAD;
  194 
  195         /* register all ports this card has */
  196         for (i = 0; i < num_ports; i++)
  197                 daic_register_port(sc, i);
  198 }
  199 
  200 /*---------------------------------------------------------------------------*
  201  * handle interrupts for one port of the card
  202  *---------------------------------------------------------------------------*/
  203 static int
  204 daic_handle_intr(sc, port)
  205         struct daic_softc *sc;
  206         int port;
  207 {
  208         struct outcallentry *assoc;
  209         struct daic_unit * du = &sc->sc_port[port];
  210         int off = port * DAIC_ISA_MEMSIZE;
  211         u_int8_t rc, rcid;
  212         u_int8_t ind, indid;
  213         int chan;
  214 
  215         /* check if we caused the interrupt */
  216         if (!bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_IRQ+off))
  217                 return 0;       /* nope, exit */
  218 
  219         /* is the card in running state yet? */
  220         if (du->du_state == DAIC_STATE_TESTING) {
  221                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
  222                 du->du_state = DAIC_STATE_RUNNING;
  223                 wakeup(du);
  224                 goto done;
  225         }
  226 
  227         /* what caused the interrupt? */
  228         /* (1) Check for a return code */
  229         rc = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off);
  230         rcid = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RCID+off);
  231         if (!rc) goto check_ind;
  232 
  233         /* maybe an assign answer (positive or negative) */
  234         if (rc == DAIC_RC_ASSIGN_OK) {
  235                 du->du_assign_res = rcid;
  236                 /* assing rc is special, we tell the card it's done */
  237                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, 0);
  238                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
  239                 /* we handle some types of assigns to global dchannel id's automaticaly */
  240                 if (du->du_assign & DAIC_ASSIGN_GLOBAL) {
  241                         du->du_global_dchan = rcid;
  242                         du->du_assign &= ~(DAIC_ASSIGN_GLOBAL|DAIC_ASSIGN_PENDING);
  243                         if (du->du_assign & DAIC_ASSIGN_SLEEPING) {
  244                                 du->du_assign = 0;
  245                                 wakeup(&du->du_assign_res);
  246                         }
  247                 } else {
  248                         wakeup(&du->du_assign);
  249                 }
  250                 goto check_ind;
  251         } else if ((rc & DAIC_RC_ASSIGN_MASK) == DAIC_RC_ASSIGN_RC) {
  252                 printf("%s: assign request failed, error 0x%02x: %s\n",
  253                         sc->sc_dev.dv_xname, rc & DAIC_RC_ERRMASK,
  254                         err_codes[rc & DAIC_RC_ERRMASK]);
  255                 du->du_assign_res = 0;
  256                 /* assing rc is special, we tell the card it's done */
  257                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, 0);
  258                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
  259                 /* that's it */
  260                 wakeup(&du->du_assign);
  261                 goto check_ind;
  262         }
  263         if (rcid == du->du_global_dchan) {
  264                 du->du_request_res = rc;
  265                 wakeup(&du->du_request_res);
  266                 goto req_done;
  267         }
  268         for (chan = 0; chan < 2; chan++) {
  269                 if (rcid == sc->sc_con[port*2+chan].dchan_inst) {
  270                         sc->sc_con[port*2+chan].dchan_rc = rc;
  271                         wakeup(&sc->sc_con[port*2+chan].dchan_rc);
  272                         goto req_done;
  273                 } else if (rcid == sc->sc_con[port*2+chan].bchan_inst) {
  274                         sc->sc_con[port*2+chan].bchan_rc = rc;
  275                         wakeup(&sc->sc_con[port*2+chan].bchan_rc);
  276                         goto req_done;
  277                 }
  278         }
  279         TAILQ_FOREACH(assoc, &sc->sc_outcalls[port], queue) {
  280                 if (rcid == assoc->dchan_id) {
  281                         assoc->rc = rc;
  282                         wakeup(assoc);
  283                         goto req_done;
  284                 }
  285         }
  286 
  287         /* not found? */
  288         printf("%s: unknown id 0x%02x got rc 0x%02x: %s\n",
  289                 sc->sc_dev.dv_xname, rcid, rc,
  290                 err_codes[rc & DAIC_RC_ERRMASK]);
  291 
  292 req_done:
  293         bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
  294 
  295 check_ind:
  296         /* (2) Check for an indication */
  297         ind = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_IND+off);
  298         indid = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_INDID+off);
  299         if (!ind) goto done;
  300 
  301         /* incoming call routed to global dchannel task? */
  302         if (indid == du->du_global_dchan) {
  303                 if (ind == DAIC_IND_INDICATE) {
  304                         daic_indicate_ind(sc, port);
  305                 } else if (ind == DAIC_IND_INFO) {
  306                         int i;
  307 
  308                         printf("%s: got info indication\n",
  309                                 sc->sc_dev.dv_xname);
  310 
  311                         for (i = 0; i < 48; i++) {
  312                                 if (!(i % 16))
  313                                         printf("\n%02x:", i);
  314                                 printf(" %02x", bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+off+i));
  315                         }
  316                         printf("\n");
  317                 } else if (ind == DAIC_IND_HANGUP) {
  318                         printf("%s: got global HANGUP indication\n",
  319                                 sc->sc_dev.dv_xname);
  320                 } else {
  321                         printf("%s: unknown global indication: 0x%02x\n",
  322                                 sc->sc_dev.dv_xname, ind);
  323                 }
  324                 goto ind_done;
  325         }
  326 
  327         for (chan = 0; chan < 2; chan++) {
  328                 if (indid == sc->sc_con[port*2+chan].dchan_inst) {
  329                         printf("%s: D-Channel indication 0x%02x for channel %d\n",
  330                                 sc->sc_dev.dv_xname, ind, chan);
  331                         goto ind_done;
  332                 } else if (indid == sc->sc_con[port*2+chan].bchan_inst) {
  333                         printf("%s: B-Channel indication 0x%02x for channel %d\n",
  334                                 sc->sc_dev.dv_xname, ind, chan);
  335                         goto ind_done;
  336                 }
  337         }
  338 
  339         TAILQ_FOREACH(assoc, &sc->sc_outcalls[port], queue) {
  340                 if (indid == assoc->dchan_id) {
  341                         printf("%s: D-Channel indication 0x%02x for outgoing call with cdid %d\n",
  342                                 sc->sc_dev.dv_xname, ind, assoc->cdid);
  343                         goto ind_done;
  344                 }
  345         }
  346 
  347         /* not found - something's wrong! */
  348         printf("%s: got ind 0x%02x for id 0x%02x\n", sc->sc_dev.dv_xname, ind, indid);
  349 
  350 ind_done:
  351         bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_IND+off, 0);
  352 
  353 done:
  354         /* tell card we're ready for more... */
  355         bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_IRQ+off, 0);
  356 
  357         return 1;
  358 }
  359 
  360 /*---------------------------------------------------------------------------*
  361  * Handle interrupts
  362  *---------------------------------------------------------------------------*/
  363 int
  364 daic_intr(sc)
  365         struct daic_softc *sc;
  366 {
  367         int handeld = 0;
  368         if (sc->sc_cardtype == DAIC_TYPE_QUAD) {
  369                 int i;
  370                 for (i = 0; i < 4; i++)
  371                         handeld |= daic_handle_intr(sc, i);
  372         } else
  373                 handeld = daic_handle_intr(sc, 0);
  374         return handeld;
  375 }
  376 
  377 /*---------------------------------------------------------------------------*
  378  * Download primary protocol microcode to on-board processor
  379  *---------------------------------------------------------------------------*/
  380 static int
  381 daic_download(token, count, data)
  382         void *token;
  383         int count;
  384         struct isdn_dr_prot *data;
  385 {
  386         struct daic_unit *du = token;
  387         struct daic_softc *sc = du->du_sc;
  388         int i;
  389 
  390         if (sc->sc_cardtype != DAIC_TYPE_QUAD)
  391                 count = 1;      /* XXX - or signal error ? */
  392 
  393         for (i = 0; i < count; i++) {
  394                 int off = DAIC_ISA_MEMSIZE * i;
  395                 u_int8_t *p = data[i].microcode;
  396                 size_t s = data[i].bytecount;
  397                 u_int32_t sw_id;
  398                 int cnt, x;
  399                 for (p = data[i].microcode+4, cnt = 0; *p && cnt < 70; p++, cnt++)
  400                         ;
  401                 sw_id = p[1] | (p[2] << 8) | (p[3] << 16) | (p[4] << 24);
  402                 if (sc->sc_cardtype == DAIC_TYPE_QUAD)
  403                         printf("%s port %d: downloading %s\n",
  404                                 sc->sc_dev.dv_xname, i, data[i].microcode+4);
  405                 else
  406                         printf("%s: downloading %s\n",
  407                                 sc->sc_dev.dv_xname, data[i].microcode+4);
  408                 x = splnet();
  409                 p = data[i].microcode;
  410                 while (s > 0) {
  411                     size_t size = (s > 256) ? 256 : s;
  412                     bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_BUF+off, p, size);
  413                     p += size;
  414                     s -= size;
  415                     bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off, 1);
  416                     splx(x);
  417                     for (cnt = 0; cnt < 2*hz; cnt++) {
  418                         x = splnet();
  419                         if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off) == 0)
  420                             break;
  421                         splx(x);
  422                         tsleep(sc, 0, "daic download", 1);
  423                     }
  424                     if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off) != 0) {
  425                         splx(x);
  426                         printf("%s: download of microcode failed\n",
  427                                 sc->sc_dev.dv_xname);
  428                         return EIO;
  429                     }
  430                 }
  431 
  432                 /* configure microcode - no parameters yet - XXX */
  433                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_TEI+off, 0);
  434                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_NT2+off, 0);
  435                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_ZERO+off, 0);
  436                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_WATCHDOG+off, 0);
  437                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_PERMANENT+off, 0);
  438                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_XINTERFACE+off, 0);
  439 
  440                 /* start protocol */
  441                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off, 2);
  442 
  443                 /* wait for signature */
  444                 for (cnt = 0; cnt < 2*hz; cnt++) {
  445                         u_int16_t signature;
  446                         signature = bus_space_read_2(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_SIGNATURE+off);
  447                         if (signature == DAIC_SIGNATURE_VALUE)
  448                                 break;
  449                         if (signature) {
  450                                 if (signature != DAIC_SIGNATURE_VALUE) {
  451                                         splx(x);
  452                                         printf("%s: microcode signature bad: should be %04x, is %04x\n",
  453                                                 sc->sc_dev.dv_xname, DAIC_SIGNATURE_VALUE,signature);
  454                                         return EIO;
  455                                 }
  456                                 break;
  457                         }
  458                         splx(x);
  459                         tsleep(&sc->sc_port[i].du_state, 0, "daic protocol init", hz/25);
  460                         x = splnet();
  461                 }
  462 
  463                 /* real check: send an invalid request and wait for an interrupt */
  464                 sc->sc_port[i].du_state = DAIC_STATE_TESTING;
  465                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
  466                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQID+off, 0xff);
  467                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, 1);
  468                 splx(x);
  469                 tsleep(&sc->sc_port[i].du_state, 0, "daic irq test", 2*hz);
  470                 x = splnet();
  471                 if (sc->sc_port[i].du_state != DAIC_STATE_RUNNING) {
  472                         splx(x);
  473                         printf("%s: download interrupt test timeout\n",
  474                                 sc->sc_dev.dv_xname);
  475                         return EIO;
  476                 }
  477 
  478                 /* finish card configuration */
  479                 bus_space_write_4(sc->sc_iot, sc->sc_ioh, DAIC_SWID+off, sw_id);
  480                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_SET_CARD+off, sc->sc_cardtype);
  481                 splx(x);
  482 
  483                 /* assign global d-channel id for that port */
  484                 sc->sc_port[i].du_global_dchan =
  485                         daic_assign(sc, i, DAIC_GLOBALID_DCHAN,
  486                                 sizeof parm_global_assign, parm_global_assign);
  487 
  488                 /* send an INDICATE request to get incoming calls on this id */
  489                 x = splnet();
  490                 VOIDREQ(sc, i, DAIC_REQ_INDICATE, sc->sc_port[i].du_global_dchan);
  491                 splx(x);
  492                 tsleep(&sc->sc_port[i].du_request_res, 0, "daic request", 0);
  493                 x = splnet();
  494                 if (sc->sc_port[i].du_request_res != DAIC_RC_OK) {
  495                         printf("%s: INDICATE request error (0x%02x): %s\n",
  496                                 sc->sc_dev.dv_xname, sc->sc_port[i].du_request_res,
  497                                 err_codes[sc->sc_port[i].du_request_res & DAIC_RC_ERRMASK]);
  498                         splx(x);
  499                         return EIO;
  500                 }
  501                 splx(x);
  502         }
  503         return 0;
  504 }
  505 
  506 /*---------------------------------------------------------------------------*
  507  *      Reset the card, download primary bootstrap, let it check the
  508  *      card and return the cardtype identified by the microcode
  509  *      or -1 if no known card is detected.
  510  *---------------------------------------------------------------------------*/
  511 static int
  512 daic_reset(bus, io, port, memsize)
  513         bus_space_tag_t bus;
  514         bus_space_handle_t io;
  515         int port;
  516         int *memsize;
  517 {
  518         int i, off = port * DAIC_ISA_MEMSIZE;
  519         int cardtype, mem, quiet = memsize == NULL;     /* no output if we are only probing */
  520 
  521         /* clear any pending interrupt */
  522         bus_space_read_1(bus, io, DAIC_IRQ+off);
  523         /* reset card */
  524         bus_space_write_1(bus, io, DAIC_BOOT_SET_RESET+off, 0);
  525 
  526         /* download primary bootstrap */
  527         bus_space_set_region_1(bus, io, DAIC_BOOT_START+off, 0, DAIC_BOOT_CODE-DAIC_BOOT_START);
  528         bus_space_write_region_1(bus, io, DAIC_BOOT_CODE+off, dnload, DAIC_BOOT_END-DAIC_BOOT_CODE+1);
  529         if (bus_space_read_1(bus, io, DAIC_BOOT_CTRL+off)
  530           || bus_space_read_1(bus, io, DAIC_BOOT_EBIT+off)) {
  531                 if (!quiet) printf(": shared memory test failed!\n");
  532                 return -1;
  533         }
  534         /* let card perform memory test */
  535         bus_space_write_1(bus, io, DAIC_BOOT_CTRL+off, DAIC_TEST_MEM);
  536         /* and off we go... */
  537         bus_space_write_1(bus, io, DAIC_BOOT_CLR_RESET+off, 0);
  538         /* wait for response from bootstrap */
  539         for (i = 0; i < 15000 && bus_space_read_1(bus, io, DAIC_BOOT_CTRL+off) != DAIC_TEST_RDY; i++)
  540                 DELAY(100);
  541         if (i >= 15000) {
  542                 if (!quiet) printf(": on board processor test failed!\n");
  543                 return -1;
  544         }
  545         if (bus_space_read_1(bus, io, DAIC_BOOT_EBIT+off)) {
  546                 if (!quiet) printf(": on board memory test failed at %p\n",
  547                         (void*)bus_space_read_2(bus, io, DAIC_BOOT_ELOC+off));
  548                 return -1;
  549         }
  550 
  551         /* fetch info from primary bootstrap code */
  552         cardtype = bus_space_read_1(bus, io, DAIC_BOOT_CARD+off);
  553         mem = bus_space_read_1(bus, io, DAIC_BOOT_MSIZE+off) << 4;
  554         if (memsize)
  555                 *memsize = mem;
  556 
  557         return cardtype;
  558 }
  559 
  560 /*---------------------------------------------------------------------------*
  561  * Generic diagnostic interface - pass through the microcode data
  562  * without knowing too much about it. This passes a lot work to
  563  * userland, but hey, this is only a diagnostic tool...
  564  *---------------------------------------------------------------------------*/
  565 static int
  566 daic_diagnostic(token, req)
  567         void *token;
  568         struct isdn_diagnostic_request *req;
  569 {
  570         struct daic_unit *du = token;
  571         struct daic_softc *sc = du->du_sc;
  572         int port = du->du_port;
  573         int off = port * DAIC_ISA_MEMSIZE;
  574         int rc, cnt;
  575         int s, err = 0;
  576 
  577         /* validate parameters */
  578         if (req->cmd < 0 || req->cmd > DAIC_DIAG_MAXCMD) {
  579                 printf("%s: daic_diagnostic: illegal cmd %d\n",
  580                         sc->sc_dev.dv_xname, req->cmd);
  581                 return EIO;
  582         }
  583         if (req->out_param_len > (DAIC_DIAG_DATA_SIZE+1)) {
  584                 printf("%s: daic_diagnostic: illegal out_param_len %d\n",
  585                         sc->sc_dev.dv_xname, req->out_param_len);
  586                 return EIO;
  587         }
  588 
  589         /* XXX - only for debug */
  590         if (req->cmd == 0x05) {
  591                 /* pass through request from userland */
  592 
  593                 u_int8_t id;
  594                 static u_int8_t parms[] = {
  595                         IEI_CALLID, 0x01, 0x81,
  596                         IEI_CALLINGPN, 7, NUMBER_TYPEPLAN, '9', '8', '9',  '', '2', '',
  597                         0x96, 0x01, 0x02, 0x01, 0x00,
  598                         0x00
  599                 };
  600 
  601                 /* create the d-channel task for this call */
  602                 printf("%s: assigning id for pass-through call\n", sc->sc_dev.dv_xname);
  603                 id = daic_assign(sc, port, DAIC_GLOBALID_DCHAN, sizeof(parms), parms);
  604                 printf("%s: got id 0x%02x\n", sc->sc_dev.dv_xname, id);
  605 
  606 #ifdef DAIC_DEBUG
  607                 daic_dump_request(sc, port, DAIC_REQ_CALL, id, req->in_param_len, req->in_param);
  608 #endif
  609                 daic_request(sc, port, DAIC_REQ_CALL, id, req->in_param_len, req->in_param);
  610                 return 0;
  611         }
  612 
  613         /* all these need an output parameter */
  614         if (req->out_param == NULL)
  615                 return EIO;
  616 
  617         /* check state and switch to DIAGNOSTIC */
  618         s = splnet();
  619         if (sc->sc_port[port].du_state != DAIC_STATE_RUNNING) {
  620                 splx(s);
  621                 return EWOULDBLOCK;
  622         }
  623         sc->sc_port[port].du_state = DAIC_STATE_DIAGNOSTIC;
  624         splx(s);
  625 
  626         /* set new request */
  627         bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_REQ+off, req->cmd);
  628 
  629         /* sorry, no interrupt on completition - have to poll */
  630         for (cnt = 0; cnt < 3*hz; cnt++) {
  631                 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_REQ+off) == 0
  632                    && bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off) != 0)
  633                         break;
  634                 tsleep(sc, 0, "daic diagnostic", 1);
  635         }
  636         rc = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off);
  637         if (rc == 0) {
  638                 /* stop request and return error */
  639                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_REQ+off, 0);
  640                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off, 0);
  641                 err = EIO;
  642                 goto done;
  643         }
  644         /* out param gets rc and all the data */
  645         if (req->out_param_len >= 2) {
  646                 ((u_int8_t*)(req->out_param))[0] = (u_int8_t)rc;
  647                 bus_space_read_region_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_DATA+off, ((u_int8_t*)req->out_param)+1, req->out_param_len-1);
  648         }
  649         /* acknowledge data */
  650         bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off, 0);
  651 
  652 done:   /* back to normal state */
  653         s = splnet();
  654         sc->sc_port[port].du_state = DAIC_STATE_RUNNING;
  655         splx(s);
  656 
  657         return err;
  658 }
  659 
  660 static void daic_stat(void *port, int channel, bchan_statistics_t *bsp)
  661 {
  662 }
  663 
  664 static const struct isdn_l4_bchannel_functions
  665 daic_l4_driver = {
  666         daic_bch_config,
  667         daic_bch_tx_start,
  668         daic_stat
  669 };
  670 
  671 static const struct isdn_l3_driver_functions
  672 daic_l3_functions =  {
  673         daic_ret_linktab,
  674         daic_set_link,
  675         daic_connect_request,
  676         daic_connect_response,
  677         daic_disconnect_request,
  678         daic_alert_request,
  679         daic_download,
  680         daic_diagnostic,
  681         daic_mgmt_command
  682 };
  683 
  684 /*---------------------------------------------------------------------------*
  685  *      Register one port and attach it to the upper layers
  686  *---------------------------------------------------------------------------*/
  687 static void
  688 daic_register_port(struct daic_softc *sc, int port)
  689 {
  690         int chan;
  691         char cardname[80], devname[80];
  692         struct isdn_l3_driver * l3drv;
  693 
  694         sc->sc_port[port].du_port = port;
  695         sc->sc_port[port].du_sc = sc;
  696 
  697         /* make sure this hardware driver type is known to layer 4 */
  698         if (sc->sc_cardtype == DAIC_TYPE_QUAD)
  699                 snprintf(devname, sizeof(devname), "%s port %d",
  700                     sc->sc_dev.dv_xname, port);
  701         else
  702                 strlcpy(devname, sc->sc_dev.dv_xname, sizeof(devname));
  703         snprintf(cardname, sizeof(cardname), "EICON.Diehl %s",
  704             cardtypename(sc->sc_cardtype));
  705         l3drv = isdn_attach_isdnif(
  706             devname, cardname, &sc->sc_port[port], &daic_l3_functions,
  707             NBCH_BRI);
  708         sc->sc_port[port].du_l3 = l3drv;
  709 
  710         /* initialize linktabs for this port */
  711         for (chan = 0; chan < 2; chan++) {
  712                 isdn_link_t *lt = &sc->sc_con[port*2+chan].isdn_linktab;
  713                 lt->l1token = &sc->sc_port[port];
  714                 lt->channel = chan;
  715                 lt->tx_queue = &sc->sc_con[port*2+chan].tx_queue;
  716                 lt->rx_queue = &sc->sc_con[port*2+chan].rx_queue;
  717         }
  718         TAILQ_INIT(&sc->sc_outcalls[port]);
  719 
  720         isdn_isdnif_ready(l3drv->isdnif);
  721 }
  722 
  723 /*---------------------------------------------------------------------------*
  724  *      return the address of daic drivers linktab
  725  *---------------------------------------------------------------------------*/
  726 static isdn_link_t *
  727 daic_ret_linktab(void *token, int channel)
  728 {
  729         struct daic_unit *du = token;
  730         struct daic_softc *sc = du->du_sc;
  731         int port = du->du_port;
  732         struct daic_connection *con = &sc->sc_con[port*2+channel];
  733 
  734         return(&con->isdn_linktab);
  735 }
  736 
  737 /*---------------------------------------------------------------------------*
  738  *      set the driver linktab in the b channel softc
  739  *---------------------------------------------------------------------------*/
  740 static void
  741 daic_set_link(void *token, int channel, const struct isdn_l4_driver_functions *l4_driver, void *l4_inst)
  742 {
  743         struct daic_unit *du = token;
  744         struct daic_softc *sc = du->du_sc;
  745         int port = du->du_port;
  746         struct daic_connection *con = &sc->sc_con[port*2+channel];
  747 
  748         con->l4_driver = l4_driver;
  749         con->l4_driver_softc = l4_inst;
  750 }
  751 
  752 /*---------------------------------------------------------------------------*
  753  *      Send a request to the card.
  754  *---------------------------------------------------------------------------*/
  755 static void
  756 daic_request(
  757         struct daic_softc *sc,          /* ourself */
  758         int port,                       /* and the port on this card */
  759         u_int req,                      /* the request to send */
  760         u_int id,                       /* id of communication task */
  761         bus_size_t parmsize,            /* size of parms including the terminating zero */
  762         const u_int8_t *parms)          /* pointer to parms to pass */
  763 {
  764         int off = port*DAIC_ISA_MEMSIZE;
  765 
  766         /* spin while card is yet busy */
  767         while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ))
  768                 ;       /* unlikely to happen with this driver */
  769 
  770         /* output parameters */
  771         bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_XBUFFER+off, parms, parmsize);
  772 
  773         /* output request and id */
  774         bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQID+off, id);
  775         bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, req);
  776 }
  777 
  778 /*---------------------------------------------------------------------------*
  779  *      Assign a unique instance id for some communication class
  780  *      on the card. Only one assign request may be running on a
  781  *      port at any time, handle this and return the instance id.
  782  *---------------------------------------------------------------------------*/
  783 static u_int
  784 daic_assign(
  785         struct daic_softc *sc,  /* our state and port no */
  786         int port,
  787         u_int classid,          /* Diehl calls this "global instance id" */
  788         bus_size_t parmsize,    /* sizeof parameter arra */
  789         const u_int8_t *parms)  /* task instance parameters */
  790 {
  791         static char wchan[] = "daic assign";
  792         u_int8_t id;
  793         int x;
  794 
  795         /* there only may be one assignment running concurrently */
  796                 x = splnet();
  797         for (;;) {
  798                 if (!(sc->sc_port[port].du_assign & DAIC_ASSIGN_PENDING))
  799                         break;  /* we got it! */
  800 
  801                 /* somebody else is assigning, record state and sleep */
  802                 sc->sc_port[port].du_assign |= DAIC_ASSIGN_SLEEPING;
  803                 tsleep(&sc->sc_port[port].du_assign_res, 0, wchan, 0);
  804         }
  805 
  806         /* put parameters and request to card */
  807         sc->sc_port[port].du_assign |= DAIC_ASSIGN_PENDING;
  808         daic_request(sc, port, DAIC_REQ_ASSIGN, classid, parmsize, parms);
  809 
  810         /* wait for completition of assignment by the card */
  811         tsleep(&sc->sc_port[port].du_assign, 0, wchan, 0);
  812         id = sc->sc_port[port].du_assign_res;
  813 
  814         /* have we lost our global dchannel id in the meantime? */
  815         if (sc->sc_port[port].du_assign & DAIC_ASSIGN_NOGLOBAL) {
  816                 /* start an assign request and let the result
  817                    be handled by the interrupt handler - we don't
  818                    have to wait for it here. As the assign lock
  819                    isn't freed, we don't wake up others... */
  820                 sc->sc_port[port].du_assign &= ~DAIC_ASSIGN_NOGLOBAL;
  821                 sc->sc_port[port].du_assign |= DAIC_ASSIGN_PENDING|DAIC_ASSIGN_GLOBAL;
  822                 daic_request(sc, port, DAIC_REQ_ASSIGN, DAIC_GLOBALID_DCHAN,
  823                         sizeof parm_global_assign, parm_global_assign);
  824                 splx(x);
  825                 return id;
  826         }
  827 
  828         /* XXX - review this, can't remember why I did it this complicated */
  829 
  830         /* unlock and wakup others, if any */
  831         if (sc->sc_port[port].du_assign & DAIC_ASSIGN_SLEEPING) {
  832                 sc->sc_port[port].du_assign = 0;
  833                 wakeup(&sc->sc_port[port].du_assign_res);
  834         } else
  835                 sc->sc_port[port].du_assign = 0;
  836         splx(x);
  837 
  838         return id;
  839 }
  840 
  841 #ifdef DAIC_DEBUG
  842 /*---------------------------------------------------------------------------*
  843  *      Debug output of request parameters
  844  *---------------------------------------------------------------------------*/
  845 static void
  846 daic_dump_request(struct daic_softc *sc, int port, u_int req, u_int id, bus_size_t parmsize, u_int8_t *parms)
  847 {
  848         int i;
  849         printf("%s: request 0x%02x to task id 0x%02x:",
  850                 sc->sc_dev.dv_xname, req, id);
  851         for (i = 0; i < parmsize; i++) {
  852                 if (i % 16 == 0)
  853                         printf("\n%02x:", i);
  854                 printf(" %02x", parms[i]);
  855         }
  856         printf("\n");
  857 }
  858 #endif
  859 
  860 /*---------------------------------------------------------------------------*
  861  *      Decode parameters of an INDICATE indication from the card
  862  *      and pass them to layer 4. Called from within an interrupt
  863  *      context.
  864  *---------------------------------------------------------------------------*/
  865 static void
  866 daic_indicate_ind(struct daic_softc *sc, int port)
  867 {
  868         int offset = port*DAIC_ISA_MEMSIZE;
  869         int i;
  870         u_int8_t ie, ielen;
  871         call_desc_t *cd;
  872 
  873         /* get and init new calldescriptor */
  874         cd = reserve_cd();      /* cdid filled in */
  875         cd->bprot = BPROT_NONE;
  876         cd->cause_in = 0;
  877         cd->cause_out = 0;
  878         cd->dst_telno[0] = '\0';
  879         cd->src_telno[0] = '\0';
  880         cd->channelid = CHAN_NO;
  881         cd->channelexcl = 0;
  882         cd->cr = -1;
  883         cd->crflag = CRF_DEST;
  884         cd->ilt = NULL;         /* reset link tab ptrs */
  885 
  886         i = 0;
  887         for (;;) {
  888                 ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
  889                 if (!ie) break;
  890                 i++;
  891                 if (ie & 0x80) continue;
  892                 ielen = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
  893                 i++;
  894                 switch (ie) {
  895                   case IEI_BEARERCAP:
  896                         ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
  897                         if (ie == 0x80 || ie == 0x89 || ie == 0x90)
  898                                 cd->bprot = BPROT_NONE;
  899                         else if (ie == 0x88)
  900                                 cd->bprot = BPROT_RHDLC;
  901                         break;
  902                   case IEI_CALLINGPN:
  903                         {
  904                                 int off;
  905                                 ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
  906                                 if (ie & 0x80)
  907                                         off = 1;
  908                                 else
  909                                         off = 2;
  910                                 bus_space_read_region_1(sc->sc_iot, sc->sc_ioh,
  911                                         DAIC_COM_RBUFFER+offset+i+off, cd->src_telno,
  912                                         ielen - off);
  913                                 cd->src_telno[ielen-off+1] = '\0';
  914                         }
  915                         break;
  916                   case IEI_CALLEDPN:
  917                         bus_space_read_region_1(sc->sc_iot, sc->sc_ioh,
  918                                 DAIC_COM_RBUFFER+offset+i+1,
  919                                 cd->dst_telno, ielen-1);
  920                         cd->dst_telno[ielen] = '\0';
  921                         break;
  922                   case IEI_CHANNELID:
  923                         ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
  924                         if ((ie & 0xf4) != 0x80)
  925                                 cd->channelid = CHAN_NO;
  926                         else {
  927                                 switch(ie & 0x03) {
  928                                   case IE_CHAN_ID_NO:   cd->channelid = CHAN_NO; break;
  929                                   case IE_CHAN_ID_B1:   cd->channelid = CHAN_B1; break;
  930                                   case IE_CHAN_ID_B2:   cd->channelid = CHAN_B2; break;
  931                                   case IE_CHAN_ID_ANY:  cd->channelid = CHAN_ANY; break;
  932                                 }
  933                                 cd->channelexcl = (ie & 0x08) >> 3;
  934                         }
  935                 }
  936                 i += ielen;
  937         }
  938         cd->event = EV_SETUP;
  939         /* ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_RSVD; */
  940 
  941         /* record the dchannel id for this call and the call descriptor */
  942         sc->sc_con[port*2+cd->channelid].dchan_inst = sc->sc_port[port].du_global_dchan;
  943         sc->sc_con[port*2+cd->channelid].cdid = cd->cdid;
  944 
  945         /* this task is busy now, we need a new global dchan id */
  946         if (sc->sc_port[port].du_assign & DAIC_ASSIGN_PENDING) {
  947                 /* argh - can't assign right now */
  948                 sc->sc_port[port].du_assign |= DAIC_ASSIGN_NOGLOBAL;
  949         } else {
  950                 /* yeah - can request the assign right away, but let the
  951                    interrupt handler autohandle the result */
  952                 sc->sc_port[port].du_assign |= DAIC_ASSIGN_PENDING|DAIC_ASSIGN_GLOBAL;
  953                 daic_request(sc, port, DAIC_REQ_ASSIGN, DAIC_GLOBALID_DCHAN,
  954                         sizeof parm_global_assign, parm_global_assign);
  955         }
  956 
  957         if (cd->bprot == BPROT_NONE)
  958                 printf("\nincoming voice call from \"%s\" to \"%s\"\n",
  959                         cd->src_telno, cd->dst_telno);
  960         else
  961                 printf("\nincoming data call from \"%s\" to \"%s\"\n",
  962                         cd->src_telno, cd->dst_telno);
  963 
  964         /* hand up call to layer 4 */
  965         i4b_l4_connect_ind(cd);
  966 }
  967 
  968 /*---------------------------------------------------------------------------*
  969  *      Layer 4 request a call setup
  970  *---------------------------------------------------------------------------*/
  971 static void
  972 daic_connect_request(struct call_desc *cd)
  973 {
  974         u_int8_t id, cpn[TELNO_MAX+4], parms[TELNO_MAX+16], *p;
  975         struct daic_unit *du = cd->ilt->l1token;
  976         struct daic_softc *sc = du->du_sc;
  977         int port = du->du_port;
  978         int x, len;
  979         struct outcallentry *assoc;
  980 
  981         /* to associate the cdid with the communication task
  982            we are going to create for this outgoing call,
  983            we maintain a queue of pending outgoing calls.
  984            As soon as a SETUP response is received, we move
  985            the association to the allocated b-channel. */
  986 
  987         /* configure d-channel task parameters */
  988         p = parms;
  989         *p++ = IEI_CALLID; *p++ = 0x01;
  990         if (cd->bprot == BPROT_NONE) {
  991                 *p++ = 0x82;
  992         } else if (cd->bprot == BPROT_RHDLC) {
  993                 *p++ = 0x85;
  994         } else {
  995                 printf("%s: daic_connect_request for unknown bchan protocol 0x%x\n",
  996                         sc->sc_dev.dv_xname, cd->bprot);
  997                 return;
  998         }
  999         if (cd->src_telno[0]) {
 1000                 *p++ = IEI_CALLINGPN;
 1001                 *p++ = strlen(cd->src_telno)+1;
 1002                 *p++ = NUMBER_TYPEPLAN;
 1003                 strcpy(p, cd->src_telno);
 1004                 p += strlen(p);
 1005         }
 1006         if (cd->channelid == CHAN_B1 || cd->channelid == CHAN_B2) {
 1007                 *p++ = IEI_CHANNELID;
 1008                 *p++ = 0x01;
 1009                 *p++ = 0x81 + cd->channelid;
 1010         }
 1011         if (cd->bprot == BPROT_NONE) {
 1012                 *p++ = 0x96;    /* shift6 */
 1013                 *p++ = 0x01;    /* SIN */
 1014                 *p++ = 0x02;    /* len */
 1015                 *p++ = 0x01;    /* Telephony */
 1016                 *p++ = 0x00;    /* add.info */
 1017         }
 1018         *p++ = 0;
 1019 
 1020         /* create the d-channel task for this call */
 1021         id = daic_assign(sc, port, DAIC_GLOBALID_DCHAN, p - parms, parms);
 1022 
 1023         /* map it to the call descriptor id */
 1024         assoc = malloc(sizeof(struct outcallentry), M_DEVBUF, 0);
 1025         assoc->cdid = cd->cdid;
 1026         assoc->dchan_id = id;
 1027         x = splnet();
 1028         TAILQ_INSERT_TAIL(&sc->sc_outcalls[port], assoc, queue);
 1029 
 1030         /* send a call request */
 1031         len = strlen(cd->dst_telno);
 1032         cpn[0] = IEI_CALLEDPN;
 1033         cpn[1] = len+1;
 1034         cpn[2] = NUMBER_TYPEPLAN;
 1035         strcpy(cpn+3, cd->dst_telno);
 1036 #ifdef DAIC_DEBUG
 1037         daic_dump_request(sc, port, DAIC_REQ_CALL, id, len+4, cpn);
 1038 #endif
 1039         daic_request(sc, port, DAIC_REQ_CALL, id, len+4, cpn);
 1040         splx(x);
 1041         tsleep(assoc, 0, "daic call", 0);
 1042         if (assoc->rc != DAIC_RC_OK) {
 1043                 printf("%s: call request failed, error 0x%02x: %s\n",
 1044                         sc->sc_dev.dv_xname, assoc->rc & DAIC_RC_ERRMASK,
 1045                         err_codes[assoc->rc & DAIC_RC_ERRMASK]);
 1046         }
 1047 }
 1048 
 1049 /*---------------------------------------------------------------------------*
 1050  *      TODO:
 1051  *---------------------------------------------------------------------------*/
 1052 static void daic_connect_response(struct call_desc *cd, int response, int cause)
 1053 {
 1054 }
 1055 
 1056 /*---------------------------------------------------------------------------*
 1057  *      TODO:
 1058  *---------------------------------------------------------------------------*/
 1059 static void daic_disconnect_request(struct call_desc *cd, int cause)
 1060 {
 1061 }
 1062 
 1063 /*---------------------------------------------------------------------------*
 1064  *      TODO:
 1065  *---------------------------------------------------------------------------*/
 1066 static void daic_bch_config(void *token, int channel, int bprot, int updown)
 1067 {
 1068         printf("daic: bch_config\n");
 1069 }
 1070 
 1071 /*---------------------------------------------------------------------------*
 1072  *      TODO:
 1073  *---------------------------------------------------------------------------*/
 1074 static void daic_bch_tx_start(void *token, int channel)
 1075 {
 1076         printf("daic: bch_tx_start\n");
 1077 }
 1078 
 1079 /*---------------------------------------------------------------------------*
 1080  *      TODO:
 1081  *---------------------------------------------------------------------------*/
 1082 static void
 1083 daic_mgmt_command(struct isdn_l3_driver *drv, int cmd, void *parm)
 1084 {
 1085 }
 1086 
 1087 /*---------------------------------------------------------------------------*
 1088  *      TODO:
 1089  *---------------------------------------------------------------------------*/
 1090 static void
 1091 daic_alert_request(struct call_desc *cd)
 1092 {
 1093 }
 1094 

Cache object: e641b325222bfbc1eee1df121086ceb3


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.