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/pci/ifpci.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) 1999 Gary Jennejohn. All rights reserved.
    3  *
    4  *   Redistribution and use in source and binary forms, with or without
    5  *   modification, are permitted provided that the following conditions
    6  *   are met:
    7  *
    8  *   1. Redistributions of source code must retain the above copyright
    9  *      notice, this list of conditions and the following disclaimer.
   10  *   2. Redistributions in binary form must reproduce the above copyright
   11  *      notice, this list of conditions and the following disclaimer in the
   12  *      documentation and/or other materials provided with the distribution.
   13  *   3. Neither the name of the author nor the names of any co-contributors
   14  *      may be used to endorse or promote products derived from this software
   15  *      without specific prior written permission.
   16  *   4. Altered versions must be plainly marked as such, and must not be
   17  *      misrepresented as being the original software and/or documentation.
   18  *   
   19  *   THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  *   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  *   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  *   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   23  *   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  *   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  *   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  *   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  *   SUCH DAMAGE.
   30  *
   31  *---------------------------------------------------------------------------
   32  *   a lot of code was borrowed from i4b_bchan.c and i4b_hscx.c
   33  *---------------------------------------------------------------------------
   34  *
   35  *      Fritz!Card PCI driver
   36  *      ------------------------------------------------
   37  *
   38  *      $Id: ifpci.c,v 1.15 2003/10/28 17:01:19 pooka Exp $
   39  *
   40  *      last edit-date: [Fri Jan  5 11:38:58 2001]
   41  *
   42  *---------------------------------------------------------------------------*/
   43 
   44 #include <sys/cdefs.h>
   45 __KERNEL_RCSID(0, "$NetBSD: ifpci.c,v 1.15 2003/10/28 17:01:19 pooka Exp $");
   46 
   47 
   48 #include <sys/param.h>
   49 #include <sys/ioctl.h>
   50 #include <sys/kernel.h>
   51 #include <sys/systm.h>
   52 #include <sys/mbuf.h>
   53 
   54 #include <machine/bus.h>
   55 #include <sys/device.h>
   56 
   57 #include <sys/socket.h>
   58 #include <net/if.h>
   59 
   60 #include <sys/callout.h>
   61 
   62 #include <dev/pci/pcireg.h>
   63 #include <dev/pci/pcivar.h>
   64 #include <dev/pci/pcidevs.h>
   65 #include <netisdn/i4b_debug.h>
   66 #include <netisdn/i4b_ioctl.h>
   67 
   68 #include <netisdn/i4b_global.h>
   69 #include <netisdn/i4b_l2.h>
   70 #include <netisdn/i4b_l1l2.h>
   71 #include <netisdn/i4b_trace.h>
   72 #include <netisdn/i4b_mbuf.h>
   73 
   74 #include <dev/ic/isic_l1.h>
   75 #include <dev/ic/isac.h>
   76 #include <dev/ic/hscx.h>
   77 
   78 #include <dev/pci/isic_pci.h>
   79 
   80 /* PCI config map to use (only one in this driver) */
   81 #define FRITZPCI_PORT0_IO_MAPOFF        PCI_MAPREG_START+4
   82 #define FRITZPCI_PORT0_MEM_MAPOFF       PCI_MAPREG_START
   83 
   84 static isdn_link_t *avma1pp_ret_linktab(void *token, int channel);
   85 static void avma1pp_set_link(void *token, int channel, const struct isdn_l4_driver_functions *l4_driver, void *l4_driver_softc);
   86 
   87 void n_connect_request(struct call_desc *cd);
   88 void n_connect_response(struct call_desc *cd, int response, int cause);
   89 void n_disconnect_request(struct call_desc *cd, int cause);
   90 void n_alert_request(struct call_desc *cd);
   91 void n_mgmt_command(struct isdn_l3_driver *drv, int cmd, void *parm);
   92 
   93 extern const struct isdn_layer1_isdnif_driver isic_std_driver;
   94 
   95 const struct isdn_l3_driver_functions
   96 ifpci_l3_driver = {
   97         avma1pp_ret_linktab,
   98         avma1pp_set_link,
   99         n_connect_request,
  100         n_connect_response,
  101         n_disconnect_request,
  102         n_alert_request,
  103         NULL,
  104         NULL,
  105         n_mgmt_command
  106 };
  107 
  108 struct ifpci_softc {
  109         struct isic_softc sc_isic;      /* parent class */
  110 
  111         /* PCI-specific goo */
  112         void *sc_ih;                            /* interrupt handler */
  113         bus_addr_t sc_base;
  114         bus_size_t sc_size;
  115         pci_chipset_tag_t sc_pc;
  116 };
  117 
  118 /* prototypes */
  119 static void avma1pp_disable(struct isic_softc *);
  120 static int isic_hscx_fifo(l1_bchan_state_t *chan, struct isic_softc *sc);
  121 
  122 static int avma1pp_intr(void*);
  123 static void avma1pp_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size);
  124 static void avma1pp_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size);
  125 static void avma1pp_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data);
  126 static u_int8_t avma1pp_read_reg(struct isic_softc *sc, int what, bus_size_t offs);
  127 static void hscx_write_fifo(int chan, const void *buf, size_t len, struct isic_softc *sc);
  128 static void hscx_read_fifo(int chan, void *buf, size_t len, struct isic_softc *sc);
  129 static void hscx_write_reg(int chan, u_int off, u_int val, struct isic_softc *sc);
  130 static u_char hscx_read_reg(int chan, u_int off, struct isic_softc *sc);
  131 static u_int hscx_read_reg_int(int chan, u_int off, struct isic_softc *sc);
  132 static void avma1pp_bchannel_stat(isdn_layer1token, int h_chan, bchan_statistics_t *bsp);
  133 static void avma1pp_map_int(struct ifpci_softc *sc, struct pci_attach_args *pa);
  134 static void avma1pp_bchannel_setup(isdn_layer1token, int h_chan, int bprot, int activate);
  135 static void avma1pp_init_linktab(struct isic_softc *);
  136 static int ifpci_match(struct device *parent, struct cfdata *match, void *aux);
  137 static void ifpci_attach(struct device *parent, struct device *self, void *aux);
  138 static int ifpci_detach(struct device *self, int flags);
  139 static int ifpci_activate(struct device *self, enum devact act);
  140 
  141 CFATTACH_DECL(ifpci, sizeof(struct ifpci_softc),
  142     ifpci_match, ifpci_attach, ifpci_detach, ifpci_activate);
  143 
  144 /*---------------------------------------------------------------------------*
  145  *      AVM PCI Fritz!Card special registers
  146  *---------------------------------------------------------------------------*/
  147 
  148 /*
  149  *      register offsets from i/o base
  150  */
  151 #define STAT0_OFFSET            0x02
  152 #define STAT1_OFFSET            0x03
  153 #define ADDR_REG_OFFSET         0x04
  154 /*#define MODREG_OFFSET         0x06
  155 #define VERREG_OFFSET           0x07*/
  156 
  157 /* these 2 are used to select an ISAC register set */
  158 #define ISAC_LO_REG_OFFSET      0x04
  159 #define ISAC_HI_REG_OFFSET      0x06
  160 
  161 /* offset higher than this goes to the HI register set */
  162 #define MAX_LO_REG_OFFSET       0x2f
  163 
  164 /* mask for the offset */
  165 #define ISAC_REGSET_MASK        0x0f
  166 
  167 /* the offset from the base to the ISAC registers */
  168 #define ISAC_REG_OFFSET         0x10
  169 
  170 /* the offset from the base to the ISAC FIFO */
  171 #define ISAC_FIFO               0x02
  172 
  173 /* not really the HSCX, but sort of */
  174 #define HSCX_FIFO               0x00
  175 #define HSCX_STAT               0x04
  176 
  177 /*
  178  *      AVM PCI Status Latch 0 read only bits
  179  */
  180 #define ASL_IRQ_ISAC            0x01    /* ISAC  interrupt, active low */
  181 #define ASL_IRQ_HSCX            0x02    /* HSX   interrupt, active low */
  182 #define ASL_IRQ_TIMER           0x04    /* Timer interrupt, active low */
  183 #define ASL_IRQ_BCHAN           ASL_IRQ_HSCX
  184 /* actually active LOW */
  185 #define ASL_IRQ_Pending         (ASL_IRQ_ISAC | ASL_IRQ_HSCX | ASL_IRQ_TIMER)
  186 
  187 /*
  188  *      AVM Status Latch 0 write only bits
  189  */
  190 #define ASL_RESET_ALL           0x01  /* reset siemens IC's, active 1 */
  191 #define ASL_TIMERDISABLE        0x02  /* active high */
  192 #define ASL_TIMERRESET          0x04  /* active high */
  193 #define ASL_ENABLE_INT          0x08  /* active high */
  194 #define ASL_TESTBIT             0x10  /* active high */
  195 
  196 /*
  197  *      AVM Status Latch 1 write only bits
  198  */
  199 #define ASL1_INTSEL              0x0f  /* active high */
  200 #define ASL1_ENABLE_IOM          0x80  /* active high */
  201 
  202 /*
  203  * "HSCX" mode bits
  204  */
  205 #define  HSCX_MODE_ITF_FLG      0x01
  206 #define  HSCX_MODE_TRANS        0x02
  207 #define  HSCX_MODE_CCR_7        0x04
  208 #define  HSCX_MODE_CCR_16       0x08
  209 #define  HSCX_MODE_TESTLOOP     0x80
  210 
  211 /*
  212  * "HSCX" status bits
  213  */
  214 #define  HSCX_STAT_RME          0x01
  215 #define  HSCX_STAT_RDO          0x10
  216 #define  HSCX_STAT_CRCVFRRAB    0x0E
  217 #define  HSCX_STAT_CRCVFR       0x06
  218 #define  HSCX_STAT_RML_MASK     0x3f00
  219 
  220 /*
  221  * "HSCX" interrupt bits
  222  */
  223 #define  HSCX_INT_XPR           0x80
  224 #define  HSCX_INT_XDU           0x40
  225 #define  HSCX_INT_RPR           0x20
  226 #define  HSCX_INT_MASK          0xE0
  227 
  228 /*
  229  * "HSCX" command bits
  230  */
  231 #define  HSCX_CMD_XRS           0x80
  232 #define  HSCX_CMD_XME           0x01
  233 #define  HSCX_CMD_RRS           0x20
  234 #define  HSCX_CMD_XML_MASK      0x3f00
  235 
  236 /*
  237  * Commands and parameters are sent to the "HSCX" as a long, but the
  238  * fields are handled as bytes.
  239  *
  240  * The long contains:
  241  *      (prot << 16)|(txl << 8)|cmd
  242  *
  243  * where:
  244  *      prot = protocol to use
  245  *      txl = transmit length
  246  *      cmd = the command to be executed
  247  *
  248  * The fields are defined as u_char in struct isic_softc.
  249  *
  250  * Macro to coalesce the byte fields into a u_int
  251  */
  252 #define AVMA1PPSETCMDLONG(f) (f) = ((sc->avma1pp_cmd) | (sc->avma1pp_txl << 8) \
  253                                         | (sc->avma1pp_prot << 16))
  254 
  255 /*
  256  * to prevent deactivating the "HSCX" when both channels are active we
  257  * define an HSCX_ACTIVE flag which is or'd into the channel's state
  258  * flag in avma1pp_bchannel_setup upon active and cleared upon deactivation.
  259  * It is set high to allow room for new flags.
  260  */
  261 #define HSCX_AVMA1PP_ACTIVE     0x1000 
  262 
  263 static int
  264 ifpci_match(struct device *parent, struct cfdata *match, void *aux)
  265 {
  266         struct pci_attach_args *pa = aux;
  267 
  268         if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AVM &&
  269             PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AVM_FRITZ_CARD)
  270                 return 1;
  271         return 0;
  272 }
  273 
  274 static void
  275 ifpci_attach(struct device *parent, struct device *self, void *aux)
  276 {
  277         struct ifpci_softc *psc = (void*)self;
  278         struct pci_attach_args *pa = aux;
  279         struct isic_softc *sc = &psc->sc_isic;
  280         struct isdn_l3_driver *drv;
  281         u_int v;
  282 
  283         /* announce */
  284         printf(": Fritz!PCI card\n");
  285 
  286         /* initialize sc */
  287         callout_init(&sc->sc_T3_callout);
  288         callout_init(&sc->sc_T4_callout);
  289 
  290         /* setup io mappings */
  291         sc->sc_cardtyp = CARD_TYPEP_AVMA1PCI;
  292         sc->sc_num_mappings = 1;
  293         MALLOC_MAPS(sc);
  294         sc->sc_maps[0].size = 0;
  295         if (pci_mapreg_map(pa, FRITZPCI_PORT0_MEM_MAPOFF, PCI_MAPREG_TYPE_MEM, 0,
  296             &sc->sc_maps[0].t, &sc->sc_maps[0].h, &psc->sc_base, &psc->sc_size) != 0
  297            && pci_mapreg_map(pa, FRITZPCI_PORT0_IO_MAPOFF, PCI_MAPREG_TYPE_IO, 0,
  298             &sc->sc_maps[0].t, &sc->sc_maps[0].h, &psc->sc_base, &psc->sc_size) != 0) {
  299                 printf("%s: can't map card\n", sc->sc_dev.dv_xname);
  300                 return;
  301         }
  302 
  303         /* setup access routines */
  304 
  305         sc->clearirq = NULL;
  306         sc->readreg = avma1pp_read_reg;
  307         sc->writereg = avma1pp_write_reg;
  308 
  309         sc->readfifo = avma1pp_read_fifo;
  310         sc->writefifo = avma1pp_write_fifo;
  311 
  312 
  313         /* setup card type */
  314         
  315         sc->sc_cardtyp = CARD_TYPEP_AVMA1PCI;
  316 
  317         /* setup IOM bus type */
  318         
  319         sc->sc_bustyp = BUS_TYPE_IOM2;
  320 
  321         /* this is no IPAC based card */
  322         sc->sc_ipac = 0;
  323         sc->sc_bfifolen = HSCX_FIFO_LEN;
  324 
  325         /* setup interrupt mapping */
  326         avma1pp_map_int(psc, pa);
  327         
  328         /* init the card */
  329         /* the Linux driver does this to clear any pending ISAC interrupts */
  330         /* see if it helps any - XXXX */
  331         v = 0;
  332         v = ISAC_READ(I_STAR);
  333         v = ISAC_READ(I_MODE);
  334         v = ISAC_READ(I_ADF2);
  335         v = ISAC_READ(I_ISTA);
  336         if (v & ISAC_ISTA_EXI)
  337         {
  338                  v = ISAC_READ(I_EXIR);
  339         }
  340         v = ISAC_READ(I_CIRR);
  341         ISAC_WRITE(I_MASK, 0xff);
  342         /* the Linux driver does this to clear any pending HSCX interrupts */
  343         v = hscx_read_reg_int(0, HSCX_STAT, sc);
  344         v = hscx_read_reg_int(1, HSCX_STAT, sc);
  345 
  346         bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, ASL_RESET_ALL|ASL_TIMERDISABLE);
  347         DELAY(SEC_DELAY/100); /* 10 ms */
  348         bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, ASL_TIMERRESET|ASL_ENABLE_INT|ASL_TIMERDISABLE);
  349         DELAY(SEC_DELAY/100); /* 10 ms */
  350 
  351         /* setup i4b infrastructure (have to roll our own here) */
  352 
  353         /* sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03; */
  354          printf("%s: ISAC %s (IOM-%c)\n", sc->sc_dev.dv_xname,
  355                 "2085 Version A1/A2 or 2086/2186 Version 1.1",
  356                  sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2');
  357 
  358         /* init the ISAC */
  359         isic_isac_init(sc);
  360 
  361         /* init the "HSCX" */
  362         avma1pp_bchannel_setup(sc, HSCX_CH_A, BPROT_NONE, 0);
  363         
  364         avma1pp_bchannel_setup(sc, HSCX_CH_B, BPROT_NONE, 0);
  365 
  366         /* can't use the normal B-Channel stuff */
  367         avma1pp_init_linktab(sc);
  368 
  369         /* set trace level */
  370 
  371         sc->sc_trace = TRACE_OFF;
  372 
  373         sc->sc_state = ISAC_IDLE;
  374 
  375         sc->sc_ibuf = NULL;
  376         sc->sc_ib = NULL;
  377         sc->sc_ilen = 0;
  378 
  379         sc->sc_obuf = NULL;
  380         sc->sc_op = NULL;
  381         sc->sc_ol = 0;
  382         sc->sc_freeflag = 0;
  383 
  384         sc->sc_obuf2 = NULL;
  385         sc->sc_freeflag2 = 0;
  386 
  387         /* init higher protocol layers */
  388         drv = isdn_attach_isdnif(sc->sc_dev.dv_xname,
  389             "AVM Fritz!PCI", &sc->sc_l2, &ifpci_l3_driver, NBCH_BRI);
  390         sc->sc_l3token = drv;
  391         sc->sc_l2.driver = &isic_std_driver;
  392         sc->sc_l2.l1_token = sc;
  393         sc->sc_l2.drv = drv;
  394         isdn_layer2_status_ind(&sc->sc_l2, drv, STI_ATTACH, 1);
  395         isdn_isdnif_ready(drv->isdnif);
  396 }
  397 
  398 static int
  399 ifpci_detach(self, flags)
  400         struct device *self;
  401         int flags;
  402 {
  403         struct ifpci_softc *psc = (struct ifpci_softc *)self;
  404 
  405         bus_space_unmap(psc->sc_isic.sc_maps[0].t, psc->sc_isic.sc_maps[0].h, psc->sc_size);
  406         bus_space_free(psc->sc_isic.sc_maps[0].t, psc->sc_isic.sc_maps[0].h, psc->sc_size);
  407         pci_intr_disestablish(psc->sc_pc, psc->sc_ih);
  408 
  409         return (0);
  410 }
  411 
  412 int
  413 ifpci_activate(self, act)
  414         struct device *self;
  415         enum devact act;
  416 {
  417         struct ifpci_softc *psc = (struct ifpci_softc *)self;
  418         int error = 0, s;
  419 
  420         s = splnet();
  421         switch (act) {
  422         case DVACT_ACTIVATE:
  423                 error = EOPNOTSUPP;
  424                 break;
  425 
  426         case DVACT_DEACTIVATE:
  427                 psc->sc_isic.sc_intr_valid = ISIC_INTR_DYING;
  428                 isdn_layer2_status_ind(&psc->sc_isic.sc_l2, psc->sc_isic.sc_l3token, STI_ATTACH, 0);
  429                 isdn_detach_isdnif(psc->sc_isic.sc_l3token);
  430                 psc->sc_isic.sc_l3token = NULL;
  431                 break;
  432         }
  433         splx(s);
  434         return (error);
  435 }
  436 
  437 /*---------------------------------------------------------------------------*
  438  *      AVM read fifo routines
  439  *---------------------------------------------------------------------------*/
  440 
  441 static void
  442 avma1pp_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size)
  443 {
  444         switch (what) {
  445                 case ISIC_WHAT_ISAC:
  446                         bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h,  ADDR_REG_OFFSET, ISAC_FIFO);
  447                         bus_space_read_multi_1(sc->sc_maps[0].t, sc->sc_maps[0].h,  ISAC_REG_OFFSET, buf, size);
  448                         break;
  449                 case ISIC_WHAT_HSCXA:
  450                         hscx_read_fifo(0, buf, size, sc);
  451                         break;
  452                 case ISIC_WHAT_HSCXB:
  453                         hscx_read_fifo(1, buf, size, sc);
  454                         break;
  455         }
  456 }
  457 
  458 static void
  459 hscx_read_fifo(int chan, void *buf, size_t len, struct isic_softc *sc)
  460 {
  461         u_int32_t *ip;
  462         size_t cnt;
  463 
  464         bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, chan);
  465         ip = (u_int32_t *)buf;
  466         cnt = 0;
  467         /* what if len isn't a multiple of sizeof(int) and buf is */
  468         /* too small ???? */
  469         while (cnt < len)
  470         {
  471                 *ip++ = bus_space_read_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET);
  472                 cnt += 4;
  473         }
  474 }
  475 
  476 /*---------------------------------------------------------------------------*
  477  *      AVM write fifo routines
  478  *---------------------------------------------------------------------------*/
  479 
  480 static void
  481 avma1pp_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size)
  482 {
  483         switch (what) {
  484                 case ISIC_WHAT_ISAC:
  485                         bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h,  ADDR_REG_OFFSET, ISAC_FIFO);
  486                         bus_space_write_multi_1(sc->sc_maps[0].t, sc->sc_maps[0].h,  ISAC_REG_OFFSET, (u_int8_t*)buf, size);
  487                         break;
  488                 case ISIC_WHAT_HSCXA:
  489                         hscx_write_fifo(0, buf, size, sc);
  490                         break;
  491                 case ISIC_WHAT_HSCXB:
  492                         hscx_write_fifo(1, buf, size, sc);
  493                         break;
  494         }
  495 }
  496 
  497 static void
  498 hscx_write_fifo(int chan, const void *buf, size_t len, struct isic_softc *sc)
  499 {
  500         u_int32_t *ip;
  501         size_t cnt;
  502         l1_bchan_state_t *Bchan = &sc->sc_chan[chan];
  503 
  504         sc->avma1pp_cmd &= ~HSCX_CMD_XME;
  505         sc->avma1pp_txl = 0;
  506         if (Bchan->out_mbuf_cur == NULL)
  507         {
  508           if (Bchan->bprot != BPROT_NONE)
  509                  sc->avma1pp_cmd |= HSCX_CMD_XME;
  510         }
  511         if (len != sc->sc_bfifolen)
  512                 sc->avma1pp_txl = len;
  513         
  514         cnt = 0; /* borrow cnt */
  515         AVMA1PPSETCMDLONG(cnt);
  516         hscx_write_reg(chan, HSCX_STAT, cnt, sc);
  517 
  518         ip = (u_int32_t *)buf;
  519         cnt = 0;
  520         while (cnt < len)
  521         {
  522                 bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET, *ip);
  523                 ip++;
  524                 cnt += 4;
  525         }
  526 }
  527 
  528 /*---------------------------------------------------------------------------*
  529  *      AVM write register routines
  530  *---------------------------------------------------------------------------*/
  531 
  532 static void
  533 avma1pp_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)
  534 {
  535         u_char reg_bank;
  536         switch (what) {
  537                 case ISIC_WHAT_ISAC:
  538                         reg_bank = (offs > MAX_LO_REG_OFFSET) ? ISAC_HI_REG_OFFSET:ISAC_LO_REG_OFFSET;
  539                         /* set the register bank */
  540                         bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, reg_bank);
  541                         bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET + (offs & ISAC_REGSET_MASK), data);
  542                         break;
  543                 case ISIC_WHAT_HSCXA:
  544                         hscx_write_reg(0, offs, data, sc);
  545                         break;
  546                 case ISIC_WHAT_HSCXB:
  547                         hscx_write_reg(1, offs, data, sc);
  548                         break;
  549         }
  550 }
  551 
  552 static void
  553 hscx_write_reg(int chan, u_int off, u_int val, struct isic_softc *sc)
  554 {
  555         /* HACK */
  556         if (off == H_MASK)
  557                 return;
  558         /* point at the correct channel */
  559         bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, chan);
  560         bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET + off, val);
  561 }
  562 
  563 /*---------------------------------------------------------------------------*
  564  *      AVM read register routines
  565  *---------------------------------------------------------------------------*/
  566 
  567 static u_int8_t
  568 avma1pp_read_reg(struct isic_softc *sc, int what, bus_size_t offs)
  569 {
  570         u_char reg_bank;
  571         switch (what) {
  572                 case ISIC_WHAT_ISAC:
  573                         reg_bank = (offs > MAX_LO_REG_OFFSET) ? ISAC_HI_REG_OFFSET:ISAC_LO_REG_OFFSET;
  574                         /* set the register bank */
  575                         bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, reg_bank);
  576                         return(bus_space_read_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET +
  577                                 (offs & ISAC_REGSET_MASK)));
  578                 case ISIC_WHAT_HSCXA:
  579                         return hscx_read_reg(0, offs, sc);
  580                 case ISIC_WHAT_HSCXB:
  581                         return hscx_read_reg(1, offs, sc);
  582         }
  583         return 0;
  584 }
  585 
  586 static u_char
  587 hscx_read_reg(int chan, u_int off, struct isic_softc *sc)
  588 {
  589         return(hscx_read_reg_int(chan, off, sc) & 0xff);
  590 }
  591 
  592 /*
  593  * need to be able to return an int because the RBCH is in the 2nd
  594  * byte.
  595  */
  596 static u_int
  597 hscx_read_reg_int(int chan, u_int off, struct isic_softc *sc)
  598 {
  599         /* HACK */
  600         if (off == H_ISTA)
  601                 return(0);
  602         /* point at the correct channel */
  603         bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR_REG_OFFSET, chan);
  604         return(bus_space_read_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISAC_REG_OFFSET + off));
  605 }
  606 
  607 /*
  608  * this is the real interrupt routine
  609  */
  610 static void
  611 avma1pp_hscx_intr(int h_chan, u_int stat, struct isic_softc *sc)
  612 {
  613         register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
  614         int activity = -1;
  615         u_int param = 0;
  616         
  617         NDBGL1(L1_H_IRQ, "%#x", stat);
  618 
  619         if((stat & HSCX_INT_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */
  620         {
  621                 chan->stat_XDU++;                       
  622                 NDBGL1(L1_H_XFRERR, "xmit data underrun");
  623                 /* abort the transmission */
  624                 sc->avma1pp_txl = 0;
  625                 sc->avma1pp_cmd |= HSCX_CMD_XRS;
  626                 AVMA1PPSETCMDLONG(param);
  627                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
  628                 sc->avma1pp_cmd &= ~HSCX_CMD_XRS;
  629                 AVMA1PPSETCMDLONG(param);
  630                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
  631 
  632                 if (chan->out_mbuf_head != NULL)  /* don't continue to transmit this buffer */
  633                 {
  634                         i4b_Bfreembuf(chan->out_mbuf_head);
  635                         chan->out_mbuf_cur = chan->out_mbuf_head = NULL;
  636                 }
  637         }
  638 
  639         /*
  640          * The following is based on examination of the Linux driver.
  641          *
  642          * The logic here is different than with a "real" HSCX; all kinds
  643          * of information (interrupt/status bits) are in stat.
  644          *              HSCX_INT_RPR indicates a receive interrupt
  645          *                      HSCX_STAT_RDO indicates an overrun condition, abort -
  646          *                      otherwise read the bytes ((stat & HSCX_STZT_RML_MASK) >> 8)
  647          *                      HSCX_STAT_RME indicates end-of-frame and apparently any
  648          *                      CRC/framing errors are only reported in this state.
  649          *                              if ((stat & HSCX_STAT_CRCVFRRAB) != HSCX_STAT_CRCVFR)
  650          *                                      CRC/framing error
  651          */
  652         
  653         if(stat & HSCX_INT_RPR)
  654         {
  655                 register int fifo_data_len;
  656                 int error = 0;
  657                 /* always have to read the FIFO, so use a scratch buffer */
  658                 u_char scrbuf[HSCX_FIFO_LEN];
  659 
  660                 if(stat & HSCX_STAT_RDO)
  661                 {
  662                         chan->stat_RDO++;
  663                         NDBGL1(L1_H_XFRERR, "receive data overflow");
  664                         error++;                                
  665                 }
  666 
  667                 /*
  668                  * check whether we're receiving data for an inactive B-channel
  669                  * and discard it. This appears to happen for telephony when
  670                  * both B-channels are active and one is deactivated. Since
  671                  * it is not really possible to deactivate the channel in that
  672                  * case (the ASIC seems to deactivate _both_ channels), the
  673                  * "deactivated" channel keeps receiving data which can lead
  674                  * to exhaustion of mbufs and a kernel panic.
  675                  *
  676                  * This is a hack, but it's the only solution I can think of
  677                  * without having the documentation for the ASIC.
  678                  * GJ - 28 Nov 1999
  679                  */
  680                  if (chan->state == HSCX_IDLE)
  681                  {
  682                         NDBGL1(L1_H_XFRERR, "toss data from %d", h_chan);
  683                         error++;
  684                  }
  685 
  686                 fifo_data_len = ((stat & HSCX_STAT_RML_MASK) >> 8);
  687                 
  688                 if(fifo_data_len == 0)
  689                         fifo_data_len = sc->sc_bfifolen;
  690 
  691                 /* ALWAYS read data from HSCX fifo */
  692         
  693                 HSCX_RDFIFO(h_chan, scrbuf, fifo_data_len);
  694                 chan->rxcount += fifo_data_len;
  695 
  696                 /* all error conditions checked, now decide and take action */
  697                 
  698                 if(error == 0)
  699                 {
  700                         if(chan->in_mbuf == NULL)
  701                         {
  702                                 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
  703                                         panic("L1 avma1pp_hscx_intr: RME, cannot allocate mbuf!");
  704                                 chan->in_cbptr = chan->in_mbuf->m_data;
  705                                 chan->in_len = 0;
  706                         }
  707 
  708                         if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN)
  709                         {
  710                                 /* OK to copy the data */
  711                                 memcpy(chan->in_cbptr, scrbuf, fifo_data_len);
  712                                 chan->in_cbptr += fifo_data_len;
  713                                 chan->in_len += fifo_data_len;
  714 
  715                                 /* setup mbuf data length */
  716                                         
  717                                 chan->in_mbuf->m_len = chan->in_len;
  718                                 chan->in_mbuf->m_pkthdr.len = chan->in_len;
  719 
  720                                 if(sc->sc_trace & TRACE_B_RX)
  721                                 {
  722                                         struct i4b_trace_hdr hdr;
  723                                         hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
  724                                         hdr.dir = FROM_NT;
  725                                         hdr.count = ++sc->sc_trace_bcount;
  726                                         isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
  727                                 }
  728 
  729                                 if (stat & HSCX_STAT_RME)
  730                                 {
  731                                   if((stat & HSCX_STAT_CRCVFRRAB) == HSCX_STAT_CRCVFR)
  732                                   {
  733                                          (*chan->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc);
  734                                          activity = ACT_RX;
  735                                 
  736                                          /* mark buffer ptr as unused */
  737                                         
  738                                          chan->in_mbuf = NULL;
  739                                          chan->in_cbptr = NULL;
  740                                          chan->in_len = 0;
  741                                   }
  742                                   else
  743                                   {
  744                                                 chan->stat_CRC++;
  745                                                 NDBGL1(L1_H_XFRERR, "CRC/RAB");
  746                                           if (chan->in_mbuf != NULL)
  747                                           {
  748                                                   i4b_Bfreembuf(chan->in_mbuf);
  749                                                   chan->in_mbuf = NULL;
  750                                                   chan->in_cbptr = NULL;
  751                                                   chan->in_len = 0;
  752                                           }
  753                                   }
  754                                 }
  755                         } /* END enough space in mbuf */
  756                         else
  757                         {
  758                                  if(chan->bprot == BPROT_NONE)
  759                                  {
  760                                           /* setup mbuf data length */
  761                                 
  762                                           chan->in_mbuf->m_len = chan->in_len;
  763                                           chan->in_mbuf->m_pkthdr.len = chan->in_len;
  764 
  765                                           if(sc->sc_trace & TRACE_B_RX)
  766                                           {
  767                                                         struct i4b_trace_hdr hdr;
  768                                                         hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
  769                                                         hdr.dir = FROM_NT;
  770                                                         hdr.count = ++sc->sc_trace_bcount;
  771                                                         isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data);
  772                                                 }
  773 
  774                                           if(!(isdn_bchan_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len)))
  775                                                  activity = ACT_RX;
  776                                 
  777                                           /* move rx'd data to rx queue */
  778 
  779                                           if (!(IF_QFULL(&chan->rx_queue)))
  780                                           {
  781                                                 IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf);
  782                                           }
  783                                           else
  784                                           {
  785                                                 i4b_Bfreembuf(chan->in_mbuf);
  786                                           }
  787 
  788                                           /* signal upper layer that data are available */
  789                                           (*chan->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc);
  790 
  791                                           /* alloc new buffer */
  792                                 
  793                                           if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL)
  794                                                  panic("L1 avma1pp_hscx_intr: RPF, cannot allocate new mbuf!");
  795         
  796                                           /* setup new data ptr */
  797                                 
  798                                           chan->in_cbptr = chan->in_mbuf->m_data;
  799         
  800                                           /* OK to copy the data */
  801                                           memcpy(chan->in_cbptr, scrbuf, fifo_data_len);
  802 
  803                                           chan->in_cbptr += fifo_data_len;
  804                                           chan->in_len = fifo_data_len;
  805 
  806                                           chan->rxcount += fifo_data_len;
  807                                         }
  808                                  else
  809                                         {
  810                                           NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", chan->in_len);
  811                                           chan->in_cbptr = chan->in_mbuf->m_data;
  812                                           chan->in_len = 0;
  813                                         }
  814                           }
  815                 } /* if(error == 0) */
  816                 else
  817                 {
  818                         /* land here for RDO */
  819                         if (chan->in_mbuf != NULL)
  820                         {
  821                                 i4b_Bfreembuf(chan->in_mbuf);
  822                                 chan->in_mbuf = NULL;
  823                                 chan->in_cbptr = NULL;
  824                                 chan->in_len = 0;
  825                         }
  826                         sc->avma1pp_txl = 0;
  827                         sc->avma1pp_cmd |= HSCX_CMD_RRS;
  828                         AVMA1PPSETCMDLONG(param);
  829                         hscx_write_reg(h_chan, HSCX_STAT, param, sc);
  830                         sc->avma1pp_cmd &= ~HSCX_CMD_RRS;
  831                         AVMA1PPSETCMDLONG(param);
  832                         hscx_write_reg(h_chan, HSCX_STAT, param, sc);
  833                 }
  834         }
  835 
  836 
  837         /* transmit fifo empty, new data can be written to fifo */
  838         
  839         if(stat & HSCX_INT_XPR)
  840         {
  841                 /*
  842                  * for a description what is going on here, please have
  843                  * a look at isic_bchannel_start() in i4b_bchan.c !
  844                  */
  845 
  846                 NDBGL1(L1_H_IRQ, "%s: chan %d - XPR, Tx Fifo Empty!", sc->sc_dev.dv_xname, h_chan);
  847 
  848                 if(chan->out_mbuf_cur == NULL)  /* last frame is transmitted */
  849                 {
  850                         IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
  851 
  852                         if(chan->out_mbuf_head == NULL)
  853                         {
  854                                 chan->state &= ~HSCX_TX_ACTIVE;
  855                                 (*chan->l4_driver->bch_tx_queue_empty)(chan->l4_driver_softc);
  856                         }
  857                         else
  858                         {
  859                                 chan->state |= HSCX_TX_ACTIVE;
  860                                 chan->out_mbuf_cur = chan->out_mbuf_head;
  861                                 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
  862                                 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
  863 
  864                                 if(sc->sc_trace & TRACE_B_TX)
  865                                 {
  866                                         struct i4b_trace_hdr hdr;
  867                                         hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
  868                                         hdr.dir = FROM_TE;
  869                                         hdr.count = ++sc->sc_trace_bcount;
  870                                         isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
  871                                 }
  872                                 
  873                                 if(chan->bprot == BPROT_NONE)
  874                                 {
  875                                         if(!(isdn_bchan_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
  876                                                 activity = ACT_TX;
  877                                 }
  878                                 else
  879                                 {
  880                                         activity = ACT_TX;
  881                                 }
  882                         }
  883                 }
  884                         
  885                 isic_hscx_fifo(chan, sc);
  886         }
  887 
  888         /* call timeout handling routine */
  889         
  890         if(activity == ACT_RX || activity == ACT_TX)
  891                 (*chan->l4_driver->bch_activity)(chan->l4_driver_softc, activity);
  892 }
  893 
  894 /*
  895  * this is the main routine which checks each channel and then calls
  896  * the real interrupt routine as appropriate
  897  */
  898 static void
  899 avma1pp_hscx_int_handler(struct isic_softc *sc)
  900 {
  901         u_int stat;
  902 
  903         /* has to be a u_int because the byte count is in the 2nd byte */
  904         stat = hscx_read_reg_int(0, HSCX_STAT, sc);
  905         if (stat & HSCX_INT_MASK)
  906           avma1pp_hscx_intr(0, stat, sc);
  907         stat = hscx_read_reg_int(1, HSCX_STAT, sc);
  908         if (stat & HSCX_INT_MASK)
  909           avma1pp_hscx_intr(1, stat, sc);
  910 }
  911 
  912 static void
  913 avma1pp_disable(struct isic_softc *sc)
  914 {
  915         bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, ASL_RESET_ALL|ASL_TIMERDISABLE);
  916 }
  917 
  918 static int
  919 avma1pp_intr(void * parm)
  920 {
  921         struct isic_softc *sc = parm;
  922         int ret = 0;
  923 #define OURS    ret = 1
  924         u_char stat;
  925 
  926         if (sc->sc_intr_valid != ISIC_INTR_VALID)
  927                 return 0;
  928 
  929         stat = bus_space_read_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET);
  930         NDBGL1(L1_H_IRQ, "stat %x", stat);
  931         /* was there an interrupt from this card ? */
  932         if ((stat & ASL_IRQ_Pending) == ASL_IRQ_Pending)
  933                 return 0; /* no */
  934         /* interrupts are low active */
  935         if (!(stat & ASL_IRQ_TIMER))
  936           NDBGL1(L1_H_IRQ, "timer interrupt ???");
  937         if (!(stat & ASL_IRQ_HSCX))
  938         {
  939           NDBGL1(L1_H_IRQ, "HSCX");
  940                 avma1pp_hscx_int_handler(sc);
  941                 OURS;
  942         }
  943         if (!(stat & ASL_IRQ_ISAC))
  944         {
  945           NDBGL1(L1_H_IRQ, "ISAC");
  946                 for (;;) {                      
  947                         /* get isac irq status */
  948                         u_int8_t isac_irq_stat = ISAC_READ(I_ISTA);
  949                         if (!isac_irq_stat)
  950                                 break;
  951                         isic_isac_irq(sc, isac_irq_stat);
  952                 }
  953                 OURS;
  954         }
  955         return ret;
  956 }
  957 
  958 static void
  959 avma1pp_map_int(struct ifpci_softc *psc, struct pci_attach_args *pa)
  960 {
  961         struct isic_softc *sc = &psc->sc_isic;
  962         pci_chipset_tag_t pc = pa->pa_pc;
  963         pci_intr_handle_t ih;
  964         const char *intrstr;
  965 
  966         /* Map and establish the interrupt. */
  967         if (pci_intr_map(pa, &ih)) {
  968                 printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname);
  969                 avma1pp_disable(sc);
  970                 return;
  971         }
  972         psc->sc_pc = pc;
  973         intrstr = pci_intr_string(pc, ih);
  974         psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, avma1pp_intr, sc);
  975         if (psc->sc_ih == NULL) {
  976                 printf("%s: couldn't establish interrupt",
  977                     sc->sc_dev.dv_xname);
  978                 if (intrstr != NULL)
  979                         printf(" at %s", intrstr);
  980                 printf("\n");
  981                 avma1pp_disable(sc);
  982                 return;
  983         }
  984         printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
  985 }
  986 
  987 static void
  988 avma1pp_hscx_init(struct isic_softc *sc, int h_chan, int activate)
  989 {
  990         l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
  991         u_int param = 0;
  992 
  993         NDBGL1(L1_BCHAN, "%s: channel=%d, %s",
  994                 sc->sc_dev.dv_xname, h_chan, activate ? "activate" : "deactivate");
  995 
  996         if (activate == 0)
  997         {
  998                 /* only deactivate if both channels are idle */
  999                 if (sc->sc_chan[HSCX_CH_A].state != HSCX_IDLE ||
 1000                         sc->sc_chan[HSCX_CH_B].state != HSCX_IDLE)
 1001                 {
 1002                         return;
 1003                 }
 1004                 sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS;
 1005                 sc->avma1pp_prot = HSCX_MODE_TRANS;
 1006                 AVMA1PPSETCMDLONG(param);
 1007                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
 1008                 return;
 1009         }
 1010         if(chan->bprot == BPROT_RHDLC)
 1011         {
 1012                   NDBGL1(L1_BCHAN, "BPROT_RHDLC");
 1013 
 1014                 /* HDLC Frames, transparent mode 0 */
 1015                 sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS;
 1016                 sc->avma1pp_prot = HSCX_MODE_ITF_FLG;
 1017                 AVMA1PPSETCMDLONG(param);
 1018                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
 1019                 sc->avma1pp_cmd = HSCX_CMD_XRS;
 1020                 AVMA1PPSETCMDLONG(param);
 1021                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
 1022                 sc->avma1pp_cmd = 0;
 1023         }
 1024         else
 1025         {
 1026                   NDBGL1(L1_BCHAN, "BPROT_NONE??");
 1027 
 1028                 /* Raw Telephony, extended transparent mode 1 */
 1029                 sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS;
 1030                 sc->avma1pp_prot = HSCX_MODE_TRANS;
 1031                 AVMA1PPSETCMDLONG(param);
 1032                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
 1033                 sc->avma1pp_cmd = HSCX_CMD_XRS;
 1034                 AVMA1PPSETCMDLONG(param);
 1035                 hscx_write_reg(h_chan, HSCX_STAT, param, sc);
 1036                 sc->avma1pp_cmd = 0;
 1037         }
 1038 }
 1039 
 1040 static void
 1041 avma1pp_bchannel_setup(isdn_layer1token t, int h_chan, int bprot, int activate)
 1042 {
 1043         struct isic_softc *sc = (struct isic_softc*)t;
 1044         l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
 1045 
 1046         int s = splnet();
 1047         
 1048         if(activate == 0)
 1049         {
 1050                 /* deactivation */
 1051                 chan->state = HSCX_IDLE;
 1052                 avma1pp_hscx_init(sc, h_chan, activate);
 1053         }
 1054                 
 1055         NDBGL1(L1_BCHAN, "%s: channel=%d, %s",
 1056                 sc->sc_dev.dv_xname, h_chan, activate ? "activate" : "deactivate");
 1057 
 1058         /* general part */
 1059 
 1060         chan->channel = h_chan;         /* B channel */
 1061         chan->bprot = bprot;            /* B channel protocol */
 1062         chan->state = HSCX_IDLE;        /* B channel state */
 1063 
 1064         /* receiver part */
 1065 
 1066         i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */
 1067 
 1068         chan->rx_queue.ifq_maxlen = IFQ_MAXLEN;
 1069 
 1070         chan->rxcount = 0;              /* reset rx counter */
 1071         
 1072         i4b_Bfreembuf(chan->in_mbuf);   /* clean rx mbuf */
 1073 
 1074         chan->in_mbuf = NULL;           /* reset mbuf ptr */
 1075         chan->in_cbptr = NULL;          /* reset mbuf curr ptr */
 1076         chan->in_len = 0;               /* reset mbuf data len */
 1077         
 1078         /* transmitter part */
 1079 
 1080         i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */
 1081 
 1082         chan->tx_queue.ifq_maxlen = IFQ_MAXLEN;
 1083         
 1084         chan->txcount = 0;              /* reset tx counter */
 1085         
 1086         i4b_Bfreembuf(chan->out_mbuf_head);     /* clean tx mbuf */
 1087 
 1088         chan->out_mbuf_head = NULL;     /* reset head mbuf ptr */
 1089         chan->out_mbuf_cur = NULL;      /* reset current mbuf ptr */    
 1090         chan->out_mbuf_cur_ptr = NULL;  /* reset current mbuf data ptr */
 1091         chan->out_mbuf_cur_len = 0;     /* reset current mbuf data cnt */
 1092         
 1093         if(activate != 0)
 1094         {
 1095                 /* activation */
 1096                 avma1pp_hscx_init(sc, h_chan, activate);
 1097                 chan->state |= HSCX_AVMA1PP_ACTIVE;
 1098         }
 1099 
 1100         splx(s);
 1101 }
 1102 
 1103 static void
 1104 avma1pp_bchannel_start(isdn_layer1token t, int h_chan)
 1105 {
 1106         struct isic_softc *sc = (struct isic_softc*)t;
 1107         register l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
 1108         int s;
 1109         int activity = -1;
 1110 
 1111         s = splnet();                           /* enter critical section */
 1112         if(chan->state & HSCX_TX_ACTIVE)        /* already running ? */
 1113         {
 1114                 splx(s);
 1115                 return;                         /* yes, leave */
 1116         }
 1117 
 1118         /* get next mbuf from queue */
 1119         
 1120         IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head);
 1121         
 1122         if(chan->out_mbuf_head == NULL)         /* queue empty ? */
 1123         {
 1124                 splx(s);                        /* leave critical section */
 1125                 return;                         /* yes, exit */
 1126         }
 1127 
 1128         /* init current mbuf values */
 1129         
 1130         chan->out_mbuf_cur = chan->out_mbuf_head;
 1131         chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
 1132         chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;    
 1133         
 1134         /* activity indicator for timeout handling */
 1135 
 1136         if(chan->bprot == BPROT_NONE)
 1137         {
 1138                 if(!(isdn_bchan_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len)))
 1139                         activity = ACT_TX;
 1140         }
 1141         else
 1142         {
 1143                 activity = ACT_TX;
 1144         }
 1145 
 1146         chan->state |= HSCX_TX_ACTIVE;          /* we start transmitting */
 1147         
 1148         if(sc->sc_trace & TRACE_B_TX)   /* if trace, send mbuf to trace dev */
 1149         {
 1150                 struct i4b_trace_hdr hdr;
 1151                 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
 1152                 hdr.dir = FROM_TE;
 1153                 hdr.count = ++sc->sc_trace_bcount;
 1154                 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
 1155         }                       
 1156 
 1157         isic_hscx_fifo(chan, sc);
 1158 
 1159         /* call timeout handling routine */
 1160         
 1161         if(activity == ACT_RX || activity == ACT_TX)
 1162                 (*chan->l4_driver->bch_activity)(chan->l4_driver_softc, activity);
 1163 
 1164         splx(s);        
 1165 }
 1166 
 1167 /*---------------------------------------------------------------------------*
 1168  *      return the address of isic drivers linktab      
 1169  *---------------------------------------------------------------------------*/
 1170 static isdn_link_t *
 1171 avma1pp_ret_linktab(void *token, int channel)
 1172 {
 1173         struct l2_softc *l2sc = token;
 1174         struct isic_softc *sc = l2sc->l1_token;
 1175 
 1176         l1_bchan_state_t *chan = &sc->sc_chan[channel];
 1177 
 1178         return(&chan->isdn_linktab);
 1179 }
 1180  
 1181 /*---------------------------------------------------------------------------*
 1182  *      set the driver linktab in the b channel softc
 1183  *---------------------------------------------------------------------------*/
 1184 static void
 1185 avma1pp_set_link(void *token, int channel, const struct isdn_l4_driver_functions *l4_driver, void *l4_driver_softc)
 1186 {
 1187         struct l2_softc *l2sc = token;
 1188         struct isic_softc *sc = l2sc->l1_token;
 1189         l1_bchan_state_t *chan = &sc->sc_chan[channel];
 1190 
 1191         chan->l4_driver = l4_driver;
 1192         chan->l4_driver_softc = l4_driver_softc;
 1193 }
 1194 
 1195 static const struct isdn_l4_bchannel_functions
 1196 avma1pp_l4_bchannel_functions = {
 1197         avma1pp_bchannel_setup,
 1198         avma1pp_bchannel_start,
 1199         avma1pp_bchannel_stat
 1200 };
 1201 
 1202 /*---------------------------------------------------------------------------*
 1203  *      initialize our local linktab
 1204  *---------------------------------------------------------------------------*/
 1205 static void
 1206 avma1pp_init_linktab(struct isic_softc *sc)
 1207 {
 1208         l1_bchan_state_t *chan = &sc->sc_chan[HSCX_CH_A];
 1209         isdn_link_t *lt = &chan->isdn_linktab;
 1210 
 1211         /* local setup */
 1212         lt->l1token = sc;
 1213         lt->channel = HSCX_CH_A;
 1214         lt->bchannel_driver = &avma1pp_l4_bchannel_functions;
 1215         lt->tx_queue = &chan->tx_queue;
 1216 
 1217         /* used by non-HDLC data transfers, i.e. telephony drivers */
 1218         lt->rx_queue = &chan->rx_queue;
 1219 
 1220         /* used by HDLC data transfers, i.e. ipr and isp drivers */     
 1221         lt->rx_mbuf = &chan->in_mbuf;   
 1222                                                 
 1223         chan = &sc->sc_chan[HSCX_CH_B];
 1224         lt = &chan->isdn_linktab;
 1225 
 1226         lt->l1token = sc;
 1227         lt->channel = HSCX_CH_B;
 1228         lt->bchannel_driver = &avma1pp_l4_bchannel_functions;
 1229         lt->tx_queue = &chan->tx_queue;
 1230 
 1231         /* used by non-HDLC data transfers, i.e. telephony drivers */
 1232         lt->rx_queue = &chan->rx_queue;
 1233 
 1234         /* used by HDLC data transfers, i.e. ipr and isp drivers */     
 1235         lt->rx_mbuf = &chan->in_mbuf;   
 1236 }
 1237 
 1238 /*
 1239  * use this instead of isic_bchannel_stat in i4b_bchan.c because it's static
 1240  */
 1241 static void
 1242 avma1pp_bchannel_stat(isdn_layer1token t, int h_chan, bchan_statistics_t *bsp)
 1243 {
 1244         struct isic_softc *sc = (struct isic_softc*)t;
 1245         l1_bchan_state_t *chan = &sc->sc_chan[h_chan];
 1246         int s;
 1247 
 1248         s = splnet();
 1249         
 1250         bsp->outbytes = chan->txcount;
 1251         bsp->inbytes = chan->rxcount;
 1252 
 1253         chan->txcount = 0;
 1254         chan->rxcount = 0;
 1255 
 1256         splx(s);
 1257 }
 1258 
 1259 /*---------------------------------------------------------------------------*
 1260  *      fill HSCX fifo with data from the current mbuf
 1261  *      Put this here until it can go into i4b_hscx.c
 1262  *---------------------------------------------------------------------------*/
 1263 static int
 1264 isic_hscx_fifo(l1_bchan_state_t *chan, struct isic_softc *sc)
 1265 {
 1266         int len;
 1267         int nextlen;
 1268         int i;
 1269         int cmd;
 1270         /* using a scratch buffer simplifies writing to the FIFO */
 1271         u_char scrbuf[HSCX_FIFO_LEN];
 1272 
 1273         len = 0;
 1274         cmd = 0;
 1275 
 1276         /*
 1277          * fill the HSCX tx fifo with data from the current mbuf. if
 1278          * current mbuf holds less data than HSCX fifo length, try to
 1279          * get the next mbuf from (a possible) mbuf chain. if there is
 1280          * not enough data in a single mbuf or in a chain, then this
 1281          * is the last mbuf and we tell the HSCX that it has to send
 1282          * CRC and closing flag
 1283          */
 1284          
 1285         while(chan->out_mbuf_cur && len != sc->sc_bfifolen)
 1286         {
 1287                 nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len);
 1288 
 1289 #ifdef NOTDEF
 1290                 printf("i:mh=%p, mc=%p, mcp=%p, mcl=%d l=%d nl=%d # ",
 1291                         chan->out_mbuf_head,
 1292                         chan->out_mbuf_cur,                     
 1293                         chan->out_mbuf_cur_ptr,
 1294                         chan->out_mbuf_cur_len,
 1295                         len,
 1296                         nextlen);
 1297 #endif
 1298 
 1299                 cmd |= HSCX_CMDR_XTF;
 1300                 /* collect the data in the scratch buffer */
 1301                 for (i = 0; i < nextlen; i++)
 1302                         scrbuf[i + len] = chan->out_mbuf_cur_ptr[i];
 1303 
 1304                 len += nextlen;
 1305                 chan->txcount += nextlen;
 1306         
 1307                 chan->out_mbuf_cur_ptr += nextlen;
 1308                 chan->out_mbuf_cur_len -= nextlen;
 1309                         
 1310                 if(chan->out_mbuf_cur_len == 0) 
 1311                 {
 1312                         if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)
 1313                         {
 1314                                 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data;
 1315                                 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len;
 1316         
 1317                                 if(sc->sc_trace & TRACE_B_TX)
 1318                                 {
 1319                                         struct i4b_trace_hdr hdr;
 1320                                         hdr.type = (chan->channel == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2);
 1321                                         hdr.dir = FROM_TE;
 1322                                         hdr.count = ++sc->sc_trace_bcount;
 1323                                         isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data);
 1324                                 }
 1325                         }
 1326                         else
 1327                         {
 1328                                 if (chan->bprot != BPROT_NONE)
 1329                                         cmd |= HSCX_CMDR_XME;
 1330                                 i4b_Bfreembuf(chan->out_mbuf_head);
 1331                                 chan->out_mbuf_head = NULL;
 1332                         }
 1333                 }
 1334         }
 1335         /* write what we have from the scratch buf to the HSCX fifo */
 1336         if (len != 0)
 1337                 HSCX_WRFIFO(chan->channel, scrbuf, len);
 1338         return(cmd);
 1339 }

Cache object: cdc9025a875467dd4aaa159e223e563f


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