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

Cache object: 8b6dc0733588c65ecb5ae3a0943bda93


[ 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.