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/iwic_dchan.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 /*      $NetBSD: iwic_dchan.c,v 1.2 2002/09/27 15:37:27 provos Exp $    */
    2 
    3 /*
    4  * Copyright (c) 1999, 2000 Dave Boyce. All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  *---------------------------------------------------------------------------
   28  *
   29  *      i4b_iwic - isdn4bsd Winbond W6692 driver
   30  *      ----------------------------------------
   31  *
   32  * $FreeBSD$
   33  *
   34  *      last edit-date: [Tue Jan 16 13:20:14 2001]
   35  *
   36  *---------------------------------------------------------------------------*/
   37 
   38 #include <sys/cdefs.h>
   39 __KERNEL_RCSID(0, "$NetBSD: iwic_dchan.c,v 1.2 2002/09/27 15:37:27 provos Exp $");
   40 
   41 #include <sys/param.h>
   42 #include <sys/kernel.h>
   43 #include <sys/systm.h>
   44 #include <sys/mbuf.h>
   45 #include <sys/callout.h>
   46 #include <net/if.h>
   47 
   48 #include <machine/bus.h>
   49 
   50 #include <dev/pci/pcivar.h>
   51 
   52 #include <dev/pci/iwicreg.h>
   53 #include <dev/pci/iwicvar.h>
   54 
   55 #include <netisdn/i4b_global.h>
   56 #include <netisdn/i4b_mbuf.h>
   57 
   58 #define MAX_DFRAME_LEN  264
   59 
   60 static void dchan_receive(struct iwic_softc *sc, int ista);
   61 
   62 /*---------------------------------------------------------------------------*
   63  *      initialize D-channel variables and registers
   64  *---------------------------------------------------------------------------*/
   65 void
   66 iwic_dchan_init(struct iwic_softc *sc)
   67 {
   68         sc->sc_dchan.ibuf = NULL;
   69         sc->sc_dchan.rx_count = 0;
   70 
   71         sc->sc_dchan.obuf = NULL;
   72         sc->sc_dchan.obuf2 = NULL;
   73         sc->sc_dchan.tx_count = 0;
   74         sc->sc_dchan.tx_ready = 0;
   75 
   76         IWIC_WRITE(sc, D_CTL, D_CTL_SRST);
   77 
   78         DELAY(5000);
   79 
   80         IWIC_WRITE(sc, D_CTL, 0);
   81 
   82         IWIC_WRITE(sc, SQX, SQX_SCIE);
   83 
   84         IWIC_WRITE(sc, PCTL, 0x00);
   85         IWIC_WRITE(sc, MOCR, 0x00);
   86         IWIC_WRITE(sc, GCR, 0x00);
   87 
   88         IWIC_WRITE(sc, D_CMDR, D_CMDR_RRST | D_CMDR_XRST);
   89         IWIC_WRITE(sc, D_MODE, D_MODE_RACT);
   90 
   91         IWIC_WRITE(sc, D_SAM, 0xff);
   92         IWIC_WRITE(sc, D_TAM, 0xff);
   93 
   94         IWIC_WRITE(sc, D_EXIM, 0x00);
   95 }
   96 
   97 /*---------------------------------------------------------------------------*
   98  *      Extended IRQ handler for the D-channel
   99  *---------------------------------------------------------------------------*/
  100 void
  101 iwic_dchan_xirq(struct iwic_softc *sc)
  102 {
  103         int irq_stat;
  104         int stat;
  105 
  106         irq_stat = IWIC_READ(sc, D_EXIR);
  107 
  108         if (irq_stat & D_EXIR_RDOV)
  109         {
  110                 NDBGL1(L1_I_ERR, "RDOV in state %s", iwic_printstate(sc));
  111                 IWIC_WRITE(sc, D_CMDR, D_CMDR_RRST);
  112         }
  113         if (irq_stat & D_EXIR_XDUN)
  114         {
  115                 NDBGL1(L1_I_ERR, "XDUN in state %s", iwic_printstate(sc));
  116                 sc->sc_dchan.tx_ready = 0;
  117         }
  118         if (irq_stat & D_EXIR_XCOL)
  119         {
  120                 NDBGL1(L1_I_ERR, "XCOL in state %s", iwic_printstate(sc));
  121                 IWIC_WRITE(sc, D_CMDR, D_CMDR_XRST);
  122                 sc->sc_dchan.tx_ready = 0;
  123         }
  124         if (irq_stat & D_EXIR_TIN2)
  125         {
  126                 NDBGL1(L1_I_ERR, "TIN2 in state %s", iwic_printstate(sc));
  127         }
  128         if (irq_stat & D_EXIR_MOC)
  129         {
  130                 stat = IWIC_READ(sc, MOR);
  131                 NDBGL1(L1_I_ERR, "MOC in state %s, byte = 0x%x", iwic_printstate(sc), stat);
  132         }
  133 
  134         if (irq_stat & D_EXIR_ISC)
  135         {
  136                 stat = (IWIC_READ(sc, CIR)) & 0x0f;
  137 
  138                 switch (stat)
  139                 {
  140                         case CIR_CE:
  141                                 NDBGL1(L1_I_CICO, "rx CE in state %s", iwic_printstate(sc));
  142                                 iwic_next_state(sc, EV_CE);
  143                                 break;
  144                         case CIR_DRD:
  145                                 NDBGL1(L1_I_CICO, "rx DRD in state %s", iwic_printstate(sc));
  146                                 iwic_next_state(sc, EV_INFO0);
  147                                 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_IDLE);
  148                                 break;
  149                         case CIR_LD:
  150                                 NDBGL1(L1_I_CICO, "rx LD in state %s", iwic_printstate(sc));
  151                                 iwic_next_state(sc, EV_RSY);
  152                                 break;
  153                         case CIR_ARD:
  154                                 NDBGL1(L1_I_CICO, "rx ARD in state %s", iwic_printstate(sc));
  155                                 iwic_next_state(sc, EV_INFO2);
  156                                 break;
  157                         case CIR_TI:
  158                                 NDBGL1(L1_I_CICO, "rx TI in state %s", iwic_printstate(sc));
  159                                 iwic_next_state(sc, EV_INFO0);
  160                                 break;
  161                         case CIR_ATI:
  162                                 NDBGL1(L1_I_CICO, "rx ATI in state %s", iwic_printstate(sc));
  163                                 iwic_next_state(sc, EV_INFO0);
  164                                 break;
  165                         case CIR_AI8:
  166                                 NDBGL1(L1_I_CICO, "rx AI8 in state %s", iwic_printstate(sc));
  167                                 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE);
  168                                 iwic_next_state(sc, EV_INFO48);
  169                                 break;
  170                         case CIR_AI10:
  171                                 NDBGL1(L1_I_CICO, "rx AI10 in state %s", iwic_printstate(sc));
  172                                 isdn_layer2_status_ind(&sc->sc_l2, sc->sc_l3token, STI_L1STAT, LAYER_ACTIVE);
  173                                 iwic_next_state(sc, EV_INFO410);
  174                                 break;
  175                         case CIR_CD:
  176                                 NDBGL1(L1_I_CICO, "rx DIS in state %s", iwic_printstate(sc));
  177                                 iwic_next_state(sc, EV_DIS);
  178                                 break;
  179                         default:
  180                                 NDBGL1(L1_I_ERR, "ERROR, unknown indication 0x%x in state %s", stat, iwic_printstate(sc));
  181                                 iwic_next_state(sc, EV_INFO0);
  182                                 break;
  183                 }
  184         }
  185 
  186         if (irq_stat & D_EXIR_TEXP)
  187         {
  188                 NDBGL1(L1_I_ERR, "TEXP in state %s", iwic_printstate(sc));
  189         }
  190 
  191         if (irq_stat & D_EXIR_WEXP)
  192         {
  193                 NDBGL1(L1_I_ERR, "WEXP in state %s", iwic_printstate(sc));
  194         }
  195 }
  196 
  197 /*---------------------------------------------------------------------------*
  198  *      All receiving and transmitting takes place here.
  199  *---------------------------------------------------------------------------*/
  200 void
  201 iwic_dchan_xfer_irq(struct iwic_softc *sc, int ista)
  202 {
  203         NDBGL1(L1_I_MSG, "ISTA = 0x%x", ista);
  204 
  205         if (ista & (ISTA_D_RMR | ISTA_D_RME))
  206         {
  207                 /* Receive message ready */
  208                 dchan_receive(sc, ista);
  209         }
  210         if (ista & ISTA_D_XFR)
  211         {
  212                 /* Transmitter ready */
  213                 sc->sc_dchan.tx_ready = 1;
  214 
  215                 iwic_dchan_transmit(sc);
  216         }
  217 }
  218 
  219 /*---------------------------------------------------------------------------*
  220  *      disable D-channel
  221  *---------------------------------------------------------------------------*/
  222 void
  223 iwic_dchan_disable(struct iwic_softc *sc)
  224 {
  225         int s;
  226 
  227         s = splnet();
  228 
  229         if (sc->sc_dchan.obuf)
  230         {
  231                 if (sc->sc_dchan.free_obuf)
  232                         i4b_Dfreembuf(sc->sc_dchan.obuf);
  233                 sc->sc_dchan.obuf = NULL;
  234         }
  235 
  236         if (sc->sc_dchan.obuf2)
  237         {
  238                 if (sc->sc_dchan.free_obuf2)
  239                         i4b_Dfreembuf(sc->sc_dchan.obuf2);
  240                 sc->sc_dchan.obuf2 = NULL;
  241         }
  242 
  243         splx(s);
  244 
  245         IWIC_WRITE(sc, CIX, CIX_DRC);
  246 }
  247 
  248 /*---------------------------------------------------------------------------*
  249  *      queue D-channel message for transmission
  250  *---------------------------------------------------------------------------*/
  251 int
  252 iwic_dchan_data_req(struct iwic_softc *sc, struct mbuf *m, int freeflag)
  253 {
  254         int s;
  255 
  256         if (!m)
  257                 return 0;
  258 
  259         s = splnet();
  260 
  261         /* Queue message */
  262 
  263         if (sc->sc_dchan.obuf)
  264         {
  265                 if (sc->sc_dchan.obuf2)
  266                 {
  267                         NDBGL1(L1_I_ERR, "no buffer space!");
  268                 }
  269                 else
  270                 {
  271                         sc->sc_dchan.obuf2 = m;
  272                         sc->sc_dchan.free_obuf2 = freeflag;
  273                 }
  274         }
  275         else
  276         {
  277                 sc->sc_dchan.obuf = m;
  278                 sc->sc_dchan.obuf_ptr = m->m_data;
  279                 sc->sc_dchan.obuf_len = m->m_len;
  280                 sc->sc_dchan.free_obuf = freeflag;
  281         }
  282 
  283         iwic_dchan_transmit(sc);
  284 
  285         splx(s);
  286 
  287         return (0);
  288 }
  289 
  290 /*---------------------------------------------------------------------------*
  291  *      allocate an mbuf
  292  *---------------------------------------------------------------------------*/
  293 static void
  294 dchan_get_mbuf(struct iwic_softc *sc, int len)
  295 {
  296         sc->sc_dchan.ibuf = i4b_Dgetmbuf(len);
  297 
  298         if (!sc->sc_dchan.ibuf)
  299                 panic("dchan_get_mbuf: unable to allocate %d bytes for mbuf!", len);
  300                 
  301         sc->sc_dchan.ibuf_ptr = sc->sc_dchan.ibuf->m_data;
  302         sc->sc_dchan.ibuf_max_len = sc->sc_dchan.ibuf->m_len;
  303         sc->sc_dchan.ibuf_len = 0;
  304 }
  305 
  306 /*---------------------------------------------------------------------------*
  307  *      D-channel receive data interrupt
  308  *---------------------------------------------------------------------------*/
  309 static void
  310 dchan_receive(struct iwic_softc *sc, int ista)
  311 {
  312         int command = D_CMDR_RACK;
  313         
  314         if (ista & ISTA_D_RMR)
  315         {
  316                 /* Got 64 bytes in FIFO */
  317 
  318                 if (!sc->sc_dchan.ibuf)
  319                 {
  320                         dchan_get_mbuf(sc, MAX_DFRAME_LEN);
  321 
  322                 }
  323                 else if ((sc->sc_dchan.ibuf_len + MAX_DFRAME_LEN) >
  324                          sc->sc_dchan.ibuf_max_len)
  325                 {
  326                         panic("dchan_receive: not enough space in buffer!");
  327                 }
  328 
  329                 IWIC_RDDFIFO(sc, sc->sc_dchan.ibuf_ptr, 64);
  330 
  331                 sc->sc_dchan.ibuf_ptr += 64;
  332                 sc->sc_dchan.ibuf_len += 64;
  333                 sc->sc_dchan.rx_count += 64;
  334         }
  335         if (ista & ISTA_D_RME)
  336         {
  337                 /* Got end of frame */
  338                 int status;
  339 
  340                 status = IWIC_READ(sc, D_RSTA);
  341 
  342                 if (status & (D_RSTA_RDOV | D_RSTA_CRCE | D_RSTA_RMB))
  343                 {
  344                         if (status & D_RSTA_RDOV)
  345                                 NDBGL1(L1_I_ERR, "%s: D-channel Receive Data Overflow", sc->sc_dev.dv_xname);
  346                         if (status & D_RSTA_CRCE)
  347                                 NDBGL1(L1_I_ERR, "%s: D-channel CRC Error", sc->sc_dev.dv_xname);
  348                         if (status & D_RSTA_RMB)
  349                                 NDBGL1(L1_I_ERR, "%s: D-channel Receive Message Aborted", sc->sc_dev.dv_xname);
  350                         command |= D_CMDR_RRST;
  351                 }
  352                 else
  353                 {
  354                         int hi, lo;
  355                         int total_frame_len;
  356         
  357                         lo = IWIC_READ(sc, D_RBCL);
  358                         hi = IWIC_READ(sc, D_RBCH);
  359                         total_frame_len = D_RBC(hi, lo);
  360                         lo = lo & 0x3f;
  361         
  362                         if (lo == 0)
  363                                 lo = IWIC_DCHAN_FIFO_LEN;
  364         
  365                         if (!sc->sc_dchan.ibuf)
  366                         {
  367                                 dchan_get_mbuf(sc, lo);
  368                         }
  369                         else if ((sc->sc_dchan.ibuf_len + lo) >
  370                                  sc->sc_dchan.ibuf_max_len)
  371                         {
  372                                 panic("dchan_receive: buffer not long enough");
  373                         }
  374         
  375                         IWIC_RDDFIFO(sc, sc->sc_dchan.ibuf_ptr, lo);
  376                         sc->sc_dchan.ibuf_len += lo;
  377                         sc->sc_dchan.rx_count += lo;
  378         
  379                         sc->sc_dchan.ibuf->m_len = sc->sc_dchan.ibuf_len;
  380         
  381                         if(sc->sc_trace & TRACE_D_RX)
  382                         {
  383                                 i4b_trace_hdr hdr;
  384                                 hdr.type = TRC_CH_D;
  385                                 hdr.dir = FROM_NT;
  386                                 hdr.count = ++sc->sc_dchan.trace_count;
  387                                 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, sc->sc_dchan.ibuf->m_len, sc->sc_dchan.ibuf->m_data);
  388                         }
  389                         isdn_layer2_data_ind(&sc->sc_l2,sc->sc_l3token,sc->sc_dchan.ibuf);
  390                         
  391                         sc->sc_dchan.ibuf = NULL;
  392                 }
  393         }
  394         IWIC_WRITE(sc, D_CMDR, command);
  395 }
  396 
  397 /*---------------------------------------------------------------------------*
  398  *      transmit D-channel frame
  399  *---------------------------------------------------------------------------*/
  400 void
  401 iwic_dchan_transmit(struct iwic_softc *sc)
  402 {
  403         int cmd;
  404         u_char *ptr;
  405         int len;
  406 
  407         if (!sc->sc_dchan.tx_ready)
  408                 return;
  409 
  410         if (!sc->sc_dchan.obuf)
  411                 return;
  412 
  413         if (sc->sc_I430state != ST_F7)
  414                 return;
  415 
  416         ptr = sc->sc_dchan.obuf_ptr;
  417         len = min(sc->sc_dchan.obuf_len, IWIC_DCHAN_FIFO_LEN);
  418 
  419         if(sc->sc_trace & TRACE_D_TX)
  420         {
  421                 i4b_trace_hdr hdr;      
  422                 hdr.type = TRC_CH_D;
  423                 hdr.dir = FROM_TE;
  424                 hdr.count = ++sc->sc_dchan.trace_count;
  425                 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, len, ptr);
  426         }
  427 
  428         IWIC_WRDFIFO(sc, ptr, len);
  429 
  430         sc->sc_dchan.tx_count += len;
  431 
  432         if (len < sc->sc_dchan.obuf_len)
  433         {
  434                 sc->sc_dchan.obuf_ptr += len;
  435                 sc->sc_dchan.obuf_len -= len;
  436 
  437                 cmd = D_CMDR_XMS;
  438 
  439         }
  440         else
  441         {
  442                 if (sc->sc_dchan.free_obuf)
  443                         i4b_Dfreembuf(sc->sc_dchan.obuf);
  444 
  445                 sc->sc_dchan.obuf = NULL;
  446                 sc->sc_dchan.obuf_ptr = NULL;
  447                 sc->sc_dchan.obuf_len = 0;
  448 
  449                 if (sc->sc_dchan.obuf2)
  450                 {
  451                         sc->sc_dchan.obuf = sc->sc_dchan.obuf2;
  452                         sc->sc_dchan.obuf_ptr = sc->sc_dchan.obuf->m_data;
  453                         sc->sc_dchan.obuf_len = sc->sc_dchan.obuf->m_len;
  454                         sc->sc_dchan.free_obuf = sc->sc_dchan.free_obuf2;
  455 
  456                         sc->sc_dchan.obuf2 = NULL;
  457                 }
  458                 cmd = D_CMDR_XMS | D_CMDR_XME;
  459         }
  460         sc->sc_dchan.tx_ready = 0;
  461         IWIC_WRITE(sc, D_CMDR, cmd);
  462 }

Cache object: 1ed713f369e18a461e461a532048d372


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