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/ctau/ctddk.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  * DDK library for Cronyx-Tau adapters.
    3  *
    4  * Copyright (C) 1998-1999 Cronyx Engineering.
    5  * Author: Alexander Kvitchenko, <aak@cronyx.ru>
    6  *
    7  * Copyright (C) 1999-2003 Cronyx Engineering.
    8  * Author: Roman Kurakin, <rik@cronyx.ru>
    9  *
   10  * This source is derived from
   11  * Diagnose utility for Cronyx-Tau adapter:
   12  * by Serge Vakulenko, <vak@cronyx.ru>
   13  *
   14  * This software is distributed with NO WARRANTIES, not even the implied
   15  * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   16  *
   17  * Authors grant any other persons or organisations permission to use
   18  * or modify this software as long as this message is kept with the software,
   19  * all derivative works or modified versions.
   20  *
   21  * Cronyx Id: ctddk.c,v 1.1.2.3 2003/11/14 16:55:36 rik Exp $
   22  */
   23 #include <sys/cdefs.h>
   24 __FBSDID("$FreeBSD$");
   25 
   26 #include <dev/cx/machdep.h>
   27 #include <dev/ctau/ctddk.h>
   28 #include <dev/ctau/ctaureg.h>
   29 #include <dev/ctau/hdc64570.h>
   30 #include <dev/ctau/ds2153.h>
   31 #include <dev/ctau/am8530.h>
   32 #include <dev/ctau/lxt318.h>
   33 #include <dev/cx/cronyxfw.h>
   34 #include <dev/ctau/ctaufw.h>
   35 #include <dev/ctau/ctau2fw.h>
   36 
   37 #ifndef CT_DDK_NO_G703
   38 #include <dev/ctau/ctaug7fw.h>
   39 #endif
   40 
   41 #ifndef CT_DDK_NO_E1
   42 #include <dev/ctau/ctaue1fw.h>
   43 #endif
   44 
   45 static void ct_hdlc_interrupt (ct_chan_t *c, int imvr);
   46 static void ct_e1_interrupt (ct_board_t *b);
   47 static void ct_scc_interrupt (ct_board_t *b);
   48 static void ct_e1timer_interrupt (ct_chan_t *c);
   49 
   50 static short porttab [] = {            /* standard base port set */
   51         0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0,
   52         0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0
   53 };
   54 
   55 int ct_find (port_t *board_ports)
   56 {
   57         int i, n;
   58 
   59         for (i=0, n=0; porttab[i] && n<NBRD; i++)
   60                 if (ct_probe_board (porttab[i], -1, -1))
   61                         board_ports[n++] = porttab[i];
   62         return n;
   63 }
   64 
   65 int ct_open_board (ct_board_t *b, int num, port_t port, int irq, int dma)
   66 {
   67         ct_chan_t *c;
   68         const unsigned char *fw;
   69         const cr_dat_tst_t *ft;
   70         long flen;
   71 
   72         if (num >= NBRD || ! ct_probe_board (port, irq, dma))
   73                 return 0;
   74 
   75         /* init callback pointers */
   76         for (c=b->chan; c<b->chan+NCHAN; ++c) {
   77                 c->call_on_tx = 0;
   78                 c->call_on_rx = 0;
   79                 c->call_on_msig = 0;
   80                 c->call_on_scc = 0;
   81                 c->call_on_err = 0;
   82         }
   83 
   84         /* init DDK channel variables */
   85         for (c=b->chan; c<b->chan+NCHAN; ++c) {
   86                 c->sccrx_empty = c->scctx_empty = 1;
   87                 c->sccrx_b = c->sccrx_e = 0;
   88                 c->scctx_b = c->scctx_e = 0;
   89                 c->e1_first_int = 1;
   90         }
   91 
   92         /* init board structure */
   93         ct_init (b, num, port, irq, dma, ctau_fw_data, 
   94                 ctau_fw_len, ctau_fw_tvec, ctau2_fw_data);
   95 
   96         /* determine which firmware should be loaded */
   97         fw = ctau_fw_data;
   98         flen = ctau_fw_len;
   99         ft = ctau_fw_tvec;
  100         switch (b->type) {
  101         case B_TAU2:
  102         case B_TAU2_G703:
  103         case B_TAU2_E1:
  104         case B_TAU2_E1D:
  105                 fw = ctau2_fw_data;
  106                 flen = 0;
  107                 ft = 0;
  108                 break;
  109 #ifndef CT_DDK_NO_G703
  110         case B_TAU_G703:
  111                 fw = ctaug703_fw_data;
  112                 flen = ctaug703_fw_len;
  113                 ft = ctaug703_fw_tvec;
  114                 break;
  115 #endif
  116 #ifndef CT_DDK_NO_E1
  117         case B_TAU_E1:
  118                 fw = ctaue1_fw_data;
  119                 flen = ctaue1_fw_len;
  120                 ft = ctaue1_fw_tvec;
  121                 break;
  122 #endif
  123         }
  124         /* Load firmware and set up board */
  125         return ct_setup_board (b, fw, flen, ft);
  126 }
  127 
  128 /*
  129  * must be called on the exit
  130  */
  131 void ct_close_board (ct_board_t *b)
  132 {
  133         ct_setup_board (b, 0, 0, 0);
  134 
  135         /* Reset the controller. */
  136         outb (BCR0(b->port), 0);
  137 
  138         /* Disable DMA channel. */
  139         ct_disable_dma (b);
  140 
  141         ct_led (b, 0);
  142 }
  143 
  144 static void ct_g703_rate (ct_chan_t *c, unsigned long rate)
  145 {
  146         c->gopt.rate = rate;
  147         ct_setup_g703 (c->board);
  148 }
  149 
  150 /*
  151  * Set up baud rate.
  152  */
  153 static void ct_chan_baud (ct_chan_t *c, unsigned long baud)
  154 {
  155         c->baud = baud;
  156         if (baud) {
  157                 c->hopt.txs = CLK_INT;
  158         } else {
  159                 ct_set_dpll (c, 0);
  160                 c->hopt.txs = CLK_LINE;
  161         }
  162         ct_update_chan (c);
  163 }
  164 
  165 void ct_set_baud (ct_chan_t *c, unsigned long baud)
  166 {
  167         unsigned long r;
  168 
  169         if (c->mode == M_E1)
  170                 return;
  171         if (c->mode == M_G703) {
  172                 if      (baud >= 2048000)  r = 2048;
  173                 else if (baud >= 1024000)  r = 1024;
  174                 else if (baud >= 512000)   r = 512;
  175                 else if (baud >= 256000)   r = 256;
  176                 else if (baud >= 128000)   r = 128;
  177                 else                       r = 64;
  178                 ct_g703_rate (c, r);
  179         } else
  180                 ct_chan_baud (c, baud);
  181 }
  182 
  183 /*
  184  * Configure Tau/E1 board.
  185  */
  186 static void ct_e1_config (ct_board_t *b, unsigned char cfg)
  187 {
  188         if (cfg == b->opt.cfg)
  189                 return;
  190 
  191         if (cfg == CFG_B)
  192                 b->chan[1].mode = M_HDLC;
  193         else
  194                 b->chan[1].mode = M_E1;
  195 
  196         /* Recovering synchronization */
  197         if (b->opt.cfg == CFG_B) {
  198                 ct_chan_baud (b->chan+1, 0);
  199                 ct_set_invtxc (b->chan+1, 0);
  200                 ct_set_invrxc (b->chan+1, 0);
  201                 ct_set_nrzi (b->chan+1, 0);
  202         }
  203         b->opt.cfg = cfg;
  204         ct_setup_e1 (b);
  205 }
  206 
  207 /*
  208  * Config Tau/G.703 board
  209  */
  210 static void ct_g703_config (ct_board_t *b, unsigned char cfg)
  211 {
  212         if (cfg == b->opt.cfg)
  213                 return;
  214 
  215         if (cfg == CFG_B)
  216                 b->chan[1].mode = M_HDLC;
  217         else
  218                 b->chan[1].mode = M_G703;
  219 
  220         /* Recovering synchronization */
  221         if (b->opt.cfg == CFG_B) {
  222                 ct_chan_baud (b->chan+1, 0);
  223                 ct_set_invtxc (b->chan+1, 0);
  224                 ct_set_invrxc (b->chan+1, 0);
  225                 ct_set_nrzi (b->chan+1, 0);
  226         }
  227         b->opt.cfg = cfg;
  228         ct_setup_g703 (b);
  229 }
  230 
  231 int ct_set_clk (ct_chan_t *c, int clk)
  232 {
  233         if (c->num)
  234                 c->board->opt.clk1 = clk;
  235         else
  236                 c->board->opt.clk0 = clk;
  237         if (c->mode == M_E1) {
  238                 ct_setup_e1 (c->board);
  239                 return 0;
  240         } if (c->mode == M_G703) {
  241                 ct_setup_g703 (c->board);
  242                 return 0;
  243         } else
  244                 return -1;
  245 }
  246 
  247 int ct_get_clk (ct_chan_t *c)
  248 {
  249         return c->num ? c->board->opt.clk1 : c->board->opt.clk0;
  250 }
  251 
  252 int ct_set_ts (ct_chan_t *c, unsigned long ts)
  253 {
  254         if (! (c->mode == M_E1))
  255                 return -1;
  256         if (c->num)
  257                 c->board->opt.s1 = ts;
  258         else
  259                 c->board->opt.s0 = ts;
  260         ct_setup_e1 (c->board);
  261         return 0;
  262 }
  263 
  264 int ct_set_subchan (ct_board_t *b, unsigned long ts)
  265 {
  266         if (b->chan[0].mode != M_E1)
  267                 return -1;
  268         b->opt.s2 = ts;
  269         ct_setup_e1 (b);
  270         return 0;
  271 }
  272 
  273 int ct_set_higain (ct_chan_t *c, int on)
  274 {
  275         if (! (c->mode == M_E1))
  276                 return -1;
  277         c->gopt.higain = on ? 1 : 0;
  278         ct_setup_e1 (c->board);
  279         return 0;
  280 }
  281 
  282 /*
  283  * Start service channel.
  284  */
  285 void ct_start_scc (ct_chan_t *c, char *rxbuf, char *txbuf)
  286 {
  287         c->sccrx = rxbuf;
  288         c->scctx = txbuf;
  289 
  290         /* Enable interrupts from service channel. */
  291         if (c->board->type != B_TAU_E1 && c->board->type != B_TAU_E1C &&
  292             c->board->type != B_TAU2_E1)
  293                 return;
  294 
  295         cte_out2 (c->board->port, c->num ? AM_IMR : AM_IMR | AM_A,
  296                  IMR_TX | IMR_RX_ALL);
  297         cte_out2 (c->board->port, AM_MICR, MICR_MIE);
  298 }
  299 
  300 /*
  301  * Start HDLC channel.
  302  */
  303 void ct_start_chan (ct_chan_t *c, ct_buf_t *cb, unsigned long phys)
  304 {
  305         int i, ier0;
  306         unsigned long bound;
  307 
  308         if (cb) {
  309                 /* Set up descriptors, align to 64k boundary.
  310                  * If 64k boundary is inside buffers
  311                  * buffers will begin on this boundary
  312                  * (there were allocated additional space for this) */
  313                 c->tdesc = cb->descbuf;
  314                 c->tdphys[0] = phys + ((char*)c->tdesc - (char*)cb);
  315                 bound = ((c->tdphys[0] + 0xffff) & ~(0xffffUL));
  316                 if (bound < c->tdphys[0] + 2*NBUF*sizeof(ct_desc_t)) {
  317                         c->tdesc = (ct_desc_t*) ((char*) c->tdesc +
  318                                 (bound - c->tdphys[0]));
  319                         c->tdphys[0] = bound;
  320                 }
  321                 c->rdesc = c->tdesc + NBUF;
  322 
  323                 /* Set buffers. */
  324                 for (i=0; i<NBUF; ++i) {
  325                         c->rbuf[i] = cb->rbuffer[i];
  326                         c->tbuf[i] = cb->tbuffer[i];
  327                 }
  328 
  329                 /* Set buffer physical addresses */
  330                 for (i=0; i<NBUF; ++i) {
  331                         c->rphys[i] = phys + ((char*)c->rbuf[i] - (char*)cb);
  332                         c->tphys[i] = phys + ((char*)c->tbuf[i] - (char*)cb);
  333                         c->rdphys[i] = phys + ((char*)(c->rdesc+i) - (char*)cb);
  334                         c->tdphys[i] = phys + ((char*)(c->tdesc+i) - (char*)cb);
  335                 }
  336         }
  337         /* Set up block chains. */
  338         /* receive buffers */
  339         for (i=0; i<NBUF; ++i) {
  340                 B_NEXT (c->rdesc[i]) = c->rdphys[(i+1) % NBUF] & 0xffff;
  341                 B_PTR (c->rdesc[i]) = c->rphys[i];
  342                 B_LEN (c->rdesc[i]) = DMABUFSZ;
  343                 B_STATUS (c->rdesc[i]) = 0;
  344         }
  345         /* transmit buffers */
  346         for (i=0; i<NBUF; ++i) {
  347                 B_NEXT (c->tdesc[i]) = c->tdphys[(i+1) % NBUF] & 0xffff;
  348                 B_PTR (c->tdesc[i]) = c->tphys[i];
  349                 B_LEN (c->tdesc[i]) = DMABUFSZ;
  350                 B_STATUS (c->tdesc[i]) = FST_EOM;
  351                 c->attach[i] = 0;
  352         }
  353 
  354         if (c->type & T_E1) {
  355                 c->mode = M_E1;
  356                 if (c->num && c->board->opt.cfg == CFG_B)
  357                         c->mode = M_HDLC;
  358         }
  359         if (c->type & T_G703) {
  360                 c->mode = M_G703;
  361                 if (c->num && c->board->opt.cfg == CFG_B)
  362                         c->mode = M_HDLC;
  363         }
  364         ct_update_chan (c);
  365 
  366         /* enable receiver */
  367         c->rn = 0;
  368         ct_start_receiver (c, 1 , c->rphys[0], DMABUFSZ, c->rdphys[0],
  369                 c->rdphys[NBUF-1]);
  370         outb (c->IE1, inb (c->IE1) | IE1_CDCDE);
  371         outb (c->IE0, inb (c->IE0) | IE0_RX_INTE);
  372         ier0 = inb (IER0(c->board->port));
  373         ier0 |= c->num ? IER0_RX_INTE_1 : IER0_RX_INTE_0;
  374         outb (IER0(c->board->port), ier0);
  375 
  376         /* Enable transmitter */
  377         c->tn = 0;
  378         c->te = 0;
  379         ct_start_transmitter (c, 1 , c->tphys[0], DMABUFSZ, c->tdphys[0],
  380                 c->tdphys[0]);
  381         outb (c->TX.DIR, DIR_CHAIN_EOME | DIR_CHAIN_BOFE | DIR_CHAIN_COFE);
  382 
  383         /* Clear DTR and RTS */
  384         ct_set_dtr (c, 0);
  385         ct_set_rts (c, 0);
  386 }
  387 
  388 /*
  389  * Turn receiver on/off
  390  */
  391 void ct_enable_receive (ct_chan_t *c, int on)
  392 {
  393         unsigned char st3, ier0, ier1;
  394 
  395         st3 = inb (c->ST3);
  396         /* enable or disable receiver */
  397         if (on && ! (st3 & ST3_RX_ENABLED)) {
  398                 c->rn = 0;
  399                 ct_start_receiver (c, 1 , c->rphys[0], DMABUFSZ, c->rdphys[0],
  400                         c->rdphys[NBUF-1]);
  401                 /* enable status interrupt */
  402                 outb (c->IE1, inb (c->IE1) | IE1_CDCDE);
  403                 outb (c->IE0, inb (c->IE0) | IE0_RX_INTE);
  404                 ier0 = inb (IER0(c->board->port));
  405                 ier0 |= c->num ? IER0_RX_INTE_1 : IER0_RX_INTE_0;
  406                 outb (IER0(c->board->port), ier0);
  407                 ct_set_rts (c, 1);
  408         } else if (! on && (st3 & ST3_RX_ENABLED)) {
  409                 ct_set_rts (c, 0);
  410                 outb (c->CMD, CMD_RX_DISABLE);
  411 
  412                 ier0 = inb (IER0(c->board->port));
  413                 ier0 &= c->num ? ~(IER0_RX_INTE_1 | IER0_RX_RDYE_1) :
  414                         ~(IER0_RX_INTE_0 | IER0_RX_RDYE_0);
  415                 outb (IER0(c->board->port), ier0);
  416 
  417                 ier1 = inb (IER1(c->board->port));
  418                 ier1 &= c->num ? ~(IER1_RX_DMERE_1 | IER1_RX_DME_1) :
  419                         ~(IER1_RX_DMERE_0 | IER1_RX_DME_0);
  420                 outb (IER1(c->board->port), ier1);
  421         }
  422 
  423 }
  424 
  425 /*
  426  * Turn transmitter on/off
  427  */
  428 void ct_enable_transmit (ct_chan_t *c, int on)
  429 {
  430         unsigned char st3, ier0, ier1;
  431 
  432         st3 = inb (c->ST3);
  433         /* enable or disable receiver */
  434         if (on && ! (st3 & ST3_TX_ENABLED)) {
  435                 c->tn = 0;
  436                 c->te = 0;
  437                 ct_start_transmitter (c, 1 , c->tphys[0], DMABUFSZ,
  438                         c->tdphys[0], c->tdphys[0]);
  439                 outb (c->TX.DIR,
  440                         DIR_CHAIN_EOME | DIR_CHAIN_BOFE | DIR_CHAIN_COFE);
  441         } else if (! on && (st3 & ST3_TX_ENABLED)) {
  442                 outb (c->CMD, CMD_TX_DISABLE);
  443 
  444                 ier0 = inb (IER0(c->board->port));
  445                 ier0 &= c->num ? ~(IER0_TX_INTE_1 | IER0_TX_RDYE_1) :
  446                         ~(IER0_TX_INTE_0 | IER0_TX_RDYE_0);
  447                 outb (IER0(c->board->port), ier0);
  448 
  449                 ier1 = inb (IER1(c->board->port));
  450                 ier1 &= c->num ? ~(IER1_TX_DMERE_1 | IER1_TX_DME_1) :
  451                         ~(IER1_TX_DMERE_0 | IER1_TX_DME_0);
  452                 outb (IER1(c->board->port), ier1);
  453         }
  454 
  455 }
  456 
  457 int ct_set_config (ct_board_t *b, int cfg)
  458 {
  459         if (b->opt.cfg == cfg)
  460                 return 0;
  461         switch (b->type) {
  462         case B_TAU_G703:
  463         case B_TAU_G703C:
  464         case B_TAU2_G703:
  465                 if (cfg == CFG_C)
  466                         return -1;
  467                 ct_g703_config (b, cfg);
  468                 return 0;
  469         case B_TAU_E1:
  470         case B_TAU_E1C:
  471         case B_TAU_E1D:
  472         case B_TAU2_E1:
  473         case B_TAU2_E1D:
  474                 ct_e1_config (b, cfg);
  475                 return 0;
  476         default:
  477                 return cfg == CFG_A ? 0 : -1;
  478         }
  479 }
  480 
  481 int ct_get_dpll (ct_chan_t *c)
  482 {
  483         return (c->hopt.rxs == CLK_RXS_DPLL_INT);
  484 }
  485 
  486 void ct_set_dpll (ct_chan_t *c, int on)
  487 {
  488         if (on && ct_get_baud (c))
  489                 c->hopt.rxs = CLK_RXS_DPLL_INT;
  490         else
  491                 c->hopt.rxs = CLK_LINE;
  492         ct_update_chan (c);
  493 }
  494 
  495 int ct_get_nrzi (ct_chan_t *c)
  496 {
  497         return (c->opt.md2.encod == MD2_ENCOD_NRZI);
  498 }
  499 
  500 /*
  501  * Change line encoding to NRZI, default is NRZ
  502  */
  503 void ct_set_nrzi (ct_chan_t *c, int on)
  504 {
  505         c->opt.md2.encod = on ? MD2_ENCOD_NRZI : MD2_ENCOD_NRZ;
  506         outb (c->MD2, *(unsigned char*)&c->opt.md2);
  507 }
  508 
  509 /*
  510  * Transmit clock inversion
  511  */
  512 void ct_set_invtxc (ct_chan_t *c, int on)
  513 {
  514         if (on) c->board->bcr2 |=  (c->num ? BCR2_INVTXC1 : BCR2_INVTXC0);
  515         else    c->board->bcr2 &= ~(c->num ? BCR2_INVTXC1 : BCR2_INVTXC0);
  516         outb (BCR2(c->board->port), c->board->bcr2);
  517 }
  518 
  519 int ct_get_invtxc (ct_chan_t *c)
  520 {
  521         return (c->board->bcr2 & (c->num ? BCR2_INVTXC1 : BCR2_INVTXC0)) != 0;
  522 }
  523 
  524 /*
  525  * Receive clock inversion
  526  */
  527 void ct_set_invrxc (ct_chan_t *c, int on)
  528 {
  529         if (on) c->board->bcr2 |=  (c->num ? BCR2_INVRXC1 : BCR2_INVRXC0);
  530         else    c->board->bcr2 &= ~(c->num ? BCR2_INVRXC1 : BCR2_INVRXC0);
  531         outb (BCR2(c->board->port), c->board->bcr2);
  532 }
  533 
  534 int ct_get_invrxc (ct_chan_t *c)
  535 {
  536         return (c->board->bcr2 & (c->num ? BCR2_INVRXC1 : BCR2_INVRXC0)) != 0;
  537 }
  538 
  539 /*
  540  * Main interrupt handler
  541  */
  542 void ct_int_handler (ct_board_t *b)
  543 {
  544         unsigned char bsr0, imvr;
  545         ct_chan_t *c;
  546 
  547         while ((bsr0 = inb (BSR0(b->port))) & BSR0_INTR) {
  548                 if (bsr0 & BSR0_RDYERR) {
  549                         outb (BCR1(b->port), b->bcr1);
  550                 } else if (bsr0 & BSR0_GINT) {
  551                         if (b->type == B_TAU_E1 || b->type == B_TAU_E1C ||
  552                             b->type == B_TAU_E1D || b->type == B_TAU2_E1 ||
  553                             b->type == B_TAU2_E1D)
  554                                 ct_e1_interrupt (b);
  555                 } else if (bsr0 & BSR0_HDINT) {
  556                         /* Read the interrupt modified vector register. */
  557                         imvr = inb (IACK(b->port));
  558                         c = b->chan + (imvr & IMVR_CHAN1 ? 1 : 0);
  559                         ct_hdlc_interrupt (c, imvr);
  560                 }
  561         }
  562 }
  563 
  564 static void ct_e1_interrupt (ct_board_t *b)
  565 {
  566         unsigned char sr;
  567 
  568         sr = inb (E1SR(b->port));
  569 
  570         if (sr & E1SR_SCC_IRQ) ct_scc_interrupt (b);
  571         if (sr & E1SR_E0_IRQ1) ct_e1timer_interrupt (b->chan + 0);
  572         if (sr & E1SR_E1_IRQ1) ct_e1timer_interrupt (b->chan + 1);
  573 }
  574 
  575 static void ct_scc_interrupt (ct_board_t *b)
  576 {
  577         unsigned char rsr;
  578         unsigned char ivr, a = AM_A;            /* assume channel A */
  579         ct_chan_t *c = b->chan;
  580 
  581         ivr = cte_in2 (b->port, AM_IVR);
  582         if (! (ivr & IVR_A))
  583                 ++c, a = 0;                     /* really channel B */
  584 
  585         switch (ivr & IVR_REASON) {
  586         case IVR_TXRDY:                         /* transmitter empty */
  587                 c->scctx_b = (c->scctx_b + 1) % SCCBUFSZ;
  588                 if (c->scctx_b == c->scctx_e) {
  589                         c->scctx_empty = 1;
  590                         cte_out2c (c, AM_CR | CR_RST_TXINT);
  591                 } else
  592                         cte_out2d (c, c->scctx[c->scctx_b]);
  593                 break;
  594 
  595         case IVR_RXERR:                 /* receive error */
  596         case IVR_RX:                    /* receive character available */
  597                 rsr = cte_in2 (b->port, a|AM_RSR);
  598 
  599                 if (rsr & RSR_RXOVRN) {         /* rx overrun */
  600                         if (c->call_on_err)
  601                                 c->call_on_err (c, CT_SCC_OVERRUN);
  602                 } else if (rsr & RSR_FRME) {    /* frame error */
  603                         if (c->call_on_err)
  604                                 c->call_on_err (c, CT_SCC_FRAME);
  605                 } else {
  606                         c->sccrx[c->sccrx_e] = cte_in2d (c);
  607                         c->sccrx_e = (c->sccrx_e + 1) % SCCBUFSZ;
  608                         c->sccrx_empty &= 0;
  609                         if (c->call_on_scc)
  610                                 c->call_on_scc (c);
  611                         if (c->sccrx_e == c->sccrx_b && ! c->sccrx_empty)
  612                                 if (c->call_on_err)
  613                                         c->call_on_err (c, CT_SCC_OVERFLOW);
  614                 }
  615                 if (rsr)
  616                         cte_out2c (c, CR_RST_ERROR);
  617                 break;
  618 
  619         case IVR_STATUS:                /* external status interrupt */
  620                 /* Unexpected SCC status interrupt. */
  621                 cte_out2c (c, CR_RST_EXTINT);
  622                 break;
  623         }
  624 }
  625 
  626 /*
  627  * G.703 mode channel: process 1-second timer interrupts.
  628  * Read error and request registers, and fill the status field.
  629  */
  630 void ct_g703_timer (ct_chan_t *c)
  631 {
  632         int bpv, cd, tsterr, tstreq;
  633 
  634         /* Count seconds.
  635          * During the first second after the channel startup
  636          * the status registers are not stable yet,
  637          * we will so skip the first second. */
  638         ++c->cursec;
  639         if (c->mode != M_G703)
  640                 return;
  641         if (c->totsec + c->cursec <= 1)
  642                 return;
  643         c->status = 0;
  644 
  645         cd = ct_get_cd (c);
  646 
  647         bpv = inb (GERR (c->board->port)) & (c->num ? GERR_BPV1 : GERR_BPV0);
  648         outb (GERR (c->board->port), bpv);
  649 
  650         tsterr = inb (GERR (c->board->port)) & (c->num ? GERR_ERR1 : GERR_ERR0);
  651         outb (GERR (c->board->port), tsterr);
  652 
  653         tstreq = inb (GLDR (c->board->port)) &
  654                 (c->num ? GLDR_LREQ1 : GLDR_LREQ0);
  655         outb (GLDR (c->board->port), tstreq);
  656 
  657         /* Compute the SNMP-compatible channel status. */
  658         if (bpv)
  659                 ++c->currnt.bpv;          /* bipolar violation */
  660         if (! cd)
  661                 c->status |= ESTS_LOS;    /* loss of signal */
  662         if (tsterr)
  663                 c->status |= ESTS_TSTERR; /* test error */
  664         if (tstreq)
  665                 c->status |= ESTS_TSTREQ; /* test code detected */
  666 
  667         if (! c->status)
  668                 c->status = ESTS_NOALARM;
  669 
  670         /* Unavaiable second -- loss of carrier, or receiving test code. */
  671         if ((! cd) || tstreq)
  672                 /* Unavailable second -- no other counters. */
  673                 ++c->currnt.uas;
  674         else {
  675                 /* Line errored second -- any BPV. */
  676                 if (bpv)
  677                         ++c->currnt.les;
  678 
  679                 /* Collect data for computing
  680                  * degraded minutes. */
  681                 ++c->degsec;
  682                 if (cd && bpv)
  683                         ++c->degerr;
  684         }
  685 
  686         /* Degraded minutes -- having more than 50% error intervals. */
  687         if (c->cursec / 60 == 0) {
  688                 if (c->degerr*2 > c->degsec)
  689                         ++c->currnt.dm;
  690                 c->degsec = 0;
  691                 c->degerr = 0;
  692         }
  693 
  694         /* Rotate statistics every 15 minutes. */
  695         if (c->cursec > 15*60) {
  696                 int i;
  697 
  698                 for (i=47; i>0; --i)
  699                         c->interval[i] = c->interval[i-1];
  700                 c->interval[0] = c->currnt;
  701 
  702                 /* Accumulate total statistics. */
  703                 c->total.bpv   += c->currnt.bpv;
  704                 c->total.fse   += c->currnt.fse;
  705                 c->total.crce  += c->currnt.crce;
  706                 c->total.rcrce += c->currnt.rcrce;
  707                 c->total.uas   += c->currnt.uas;
  708                 c->total.les   += c->currnt.les;
  709                 c->total.es    += c->currnt.es;
  710                 c->total.bes   += c->currnt.bes;
  711                 c->total.ses   += c->currnt.ses;
  712                 c->total.oofs  += c->currnt.oofs;
  713                 c->total.css   += c->currnt.css;
  714                 c->total.dm    += c->currnt.dm;
  715                 memset (&c->currnt, 0, sizeof (c->currnt));
  716 
  717                 c->totsec += c->cursec;
  718                 c->cursec = 0;
  719         }
  720 }
  721 
  722 static void ct_e1timer_interrupt (ct_chan_t *c)
  723 {
  724         unsigned short port;
  725         unsigned char sr1, sr2, ssr;
  726         unsigned long bpv, fas, crc4, ebit, pcv, oof;
  727 
  728         port = c->num ? E1CS1(c->board->port) : E1CS0(c->board->port);
  729 
  730         sr2 = cte_ins (port, DS_SR2, 0xff);
  731         /* is it timer interrupt ? */
  732         if (! (sr2 & SR2_SEC))
  733                 return;
  734 
  735         /* first interrupts should be ignored */
  736         if (c->e1_first_int > 0) {
  737                 c->e1_first_int --;
  738                 return;
  739         }
  740 
  741         ++c->cursec;
  742         c->status = 0;
  743 
  744         /* Compute the SNMP-compatible channel status. */
  745         sr1 = cte_ins (port, DS_SR1, 0xff);
  746         ssr = cte_in (port, DS_SSR);
  747         oof = 0;
  748 
  749         if (sr1 & (SR1_RCL | SR1_RLOS))
  750                 c->status |= ESTS_LOS;          /* loss of signal */
  751         if (sr1 & SR1_RUA1)
  752                 c->status |= ESTS_AIS;          /* receiving all ones */
  753         if (c->gopt.cas && (sr1 & SR1_RSA1))
  754                 c->status |= ESTS_AIS16;        /* signaling all ones */
  755         if (c->gopt.cas && (sr1 & SR1_RDMA))
  756                 c->status |= ESTS_FARLOMF;      /* alarm in timeslot 16 */
  757         if (sr1 & SR1_RRA)
  758                 c->status |= ESTS_FARLOF;       /* far loss of framing */
  759 
  760         /* Controlled slip second -- any slip event. */
  761         if (sr1 & SR1_RSLIP) {
  762                 ++c->currnt.css;
  763         }
  764 
  765         if (ssr & SSR_SYNC) {
  766                 c->status |= ESTS_LOF;          /* loss of framing */
  767                 ++oof;                          /* out of framing */
  768         }
  769         if ((c->gopt.cas && (ssr & SSR_SYNC_CAS)) ||
  770             (c->gopt.crc4 && (ssr & SSR_SYNC_CRC4))) {
  771                 c->status |= ESTS_LOMF;         /* loss of multiframing */
  772                 ++oof;                          /* out of framing */
  773         }
  774 
  775         if (! c->status)
  776                 c->status = ESTS_NOALARM;
  777 
  778         /* Get error counters. */
  779         bpv = VCR (cte_in (port, DS_VCR1), cte_in (port, DS_VCR2));
  780         fas = FASCR (cte_in (port, DS_FASCR1), cte_in (port, DS_FASCR2));
  781         crc4 = CRCCR (cte_in (port, DS_CRCCR1), cte_in (port, DS_CRCCR2));
  782         ebit = EBCR (cte_in (port, DS_EBCR1), cte_in (port, DS_EBCR2));
  783 
  784         c->currnt.bpv += bpv;
  785         c->currnt.fse += fas;
  786         if (c->gopt.crc4) {
  787                 c->currnt.crce += crc4;
  788                 c->currnt.rcrce += ebit;
  789         }
  790 
  791         /* Path code violation is frame sync error if CRC4 disabled,
  792          * or CRC error if CRC4 enabled. */
  793         pcv = fas;
  794         if (c->gopt.crc4)
  795                 pcv += crc4;
  796 
  797         /* Unavaiable second -- receiving all ones, or
  798          * loss of carrier, or loss of signal. */
  799         if (sr1 & (SR1_RUA1 | SR1_RCL | SR1_RLOS))
  800                 /* Unavailable second -- no other counters. */
  801                 ++c->currnt.uas;
  802         else {
  803                 /* Line errored second -- any BPV. */
  804                 if (bpv)
  805                         ++c->currnt.les;
  806 
  807                 /* Errored second -- any PCV, or out of frame sync,
  808                  * or any slip events. */
  809                 if (pcv || oof || (sr1 & SR1_RSLIP))
  810                         ++c->currnt.es;
  811 
  812                 /* Severely errored framing second -- out of frame sync. */
  813                 if (oof)
  814                         ++c->currnt.oofs;
  815 
  816                 /* Severely errored seconds --
  817                  * 832 or more PCVs, or 2048 or more BPVs. */
  818                 if (bpv >= 2048 || pcv >= 832)
  819                         ++c->currnt.ses;
  820                 else {
  821                         /* Bursty errored seconds --
  822                          * no SES and more than 1 PCV. */
  823                         if (pcv > 1)
  824                                 ++c->currnt.bes;
  825 
  826                         /* Collect data for computing
  827                          * degraded minutes. */
  828                         ++c->degsec;
  829                         c->degerr += bpv + pcv;
  830                 }
  831         }
  832 
  833         /* Degraded minutes -- having error rate more than 10e-6,
  834          * not counting unavailable and severely errored seconds. */
  835         if (c->cursec / 60 == 0) {
  836                 if (c->degerr > c->degsec * 2048 / 1000)
  837                         ++c->currnt.dm;
  838                 c->degsec = 0;
  839                 c->degerr = 0;
  840         }
  841 
  842         /* Rotate statistics every 15 minutes. */
  843         if (c->cursec > 15*60) {
  844                 int i;
  845 
  846                 for (i=47; i>0; --i)
  847                         c->interval[i] = c->interval[i-1];
  848                 c->interval[0] = c->currnt;
  849 
  850                 /* Accumulate total statistics. */
  851                 c->total.bpv   += c->currnt.bpv;
  852                 c->total.fse   += c->currnt.fse;
  853                 c->total.crce  += c->currnt.crce;
  854                 c->total.rcrce += c->currnt.rcrce;
  855                 c->total.uas   += c->currnt.uas;
  856                 c->total.les   += c->currnt.les;
  857                 c->total.es    += c->currnt.es;
  858                 c->total.bes   += c->currnt.bes;
  859                 c->total.ses   += c->currnt.ses;
  860                 c->total.oofs  += c->currnt.oofs;
  861                 c->total.css   += c->currnt.css;
  862                 c->total.dm    += c->currnt.dm;
  863                 for (i=0; i<sizeof (c->currnt); ++i)
  864                         *(((char *)(&c->currnt))+i)=0;
  865 
  866                 c->totsec += c->cursec;
  867                 c->cursec = 0;
  868         }
  869 }
  870 
  871 static void ct_hdlc_interrupt (ct_chan_t *c, int imvr)
  872 {
  873         int i, dsr, st1, st2, cda;
  874 
  875         switch (imvr & IMVR_VECT_MASK) {
  876         case IMVR_RX_DMOK:              /* receive DMA normal end */
  877                 dsr = inb (c->RX.DSR);
  878                 cda = inw (c->RX.CDA);
  879                 for (i=0; i<NBUF; ++i)
  880                         if (cda == (unsigned short) c->rdphys[i])
  881                                 break;
  882                 if (i >= NBUF)
  883                         i = c->rn; /* cannot happen */
  884                 while (c->rn != i) {
  885                         int cst = B_STATUS (c->rdesc[c->rn]);
  886                         if (cst == FST_EOM) {
  887                                 /* process data */
  888                                 if (c->call_on_rx)
  889                                          c->call_on_rx (c, c->rbuf[c->rn],
  890                                                 B_LEN(c->rdesc[c->rn]));
  891                                 ++c->ipkts;
  892                                 c->ibytes += B_LEN(c->rdesc[c->rn]);
  893                         } else if (cst & ST2_OVRN) {
  894                                 /* Receive overrun error */
  895                                 if (c->call_on_err)
  896                                         c->call_on_err (c, CT_OVERRUN);
  897                                 ++c->ierrs;
  898                         } else if (cst & (ST2_HDLC_RBIT |
  899                                 ST2_HDLC_ABT | ST2_HDLC_SHRT)) {
  900                                 /* Receive frame error */
  901                                 if (c->call_on_err)
  902                                         c->call_on_err (c, CT_FRAME);
  903                                 ++c->ierrs;
  904                         } else if ((cst & ST2_HDLC_EOM)
  905                                 && (cst & ST2_HDLC_CRCE)) {
  906                                 /* Receive CRC error */
  907                                 if (c->call_on_err)
  908                                         c->call_on_err (c, CT_CRC);
  909                                 ++c->ierrs;
  910                         } else if (! (cst & ST2_HDLC_EOM)) {
  911                                 /* Frame dose not fit in the buffer.*/
  912                                 if (c->call_on_err)
  913                                         c->call_on_err (c, CT_OVERFLOW);
  914                                 ++c->ierrs;
  915                         }
  916 
  917                         B_NEXT (c->rdesc[c->rn]) =
  918                                 c->rdphys[(c->rn+1) % NBUF] & 0xffff;
  919                         B_PTR (c->rdesc[c->rn]) = c->rphys[c->rn];
  920                         B_LEN (c->rdesc[c->rn]) = DMABUFSZ;
  921                         B_STATUS (c->rdesc[c->rn]) = 0;
  922                         c->rn = (c->rn + 1) % NBUF;
  923                 }
  924                 outw (c->RX.EDA, (unsigned short) c->rdphys[(i+NBUF-1)%NBUF]);
  925                 /* Clear DMA interrupt. */
  926                 if (inb (c->RX.DSR) & DSR_DMA_ENABLE) {
  927                         outb (c->RX.DSR, dsr);
  928                 } else {
  929                         outb (c->RX.DSR, (dsr & 0xfc) | DSR_DMA_ENABLE);
  930                 }
  931                 ++c->rintr;
  932                 break;
  933 
  934         case IMVR_RX_INT:               /* receive status */
  935                 st1 = inb (c->ST1);
  936                 st2 = inb (c->ST2);
  937                 if (st1 & ST1_CDCD){
  938                         if (c->call_on_msig)
  939                                 c->call_on_msig (c);
  940                         ++c->mintr;
  941                 }
  942                 /* Clear interrupt. */
  943                 outb (c->ST1, st1);
  944                 outb (c->ST2, st2);
  945                 ++c->rintr;
  946                 break;
  947 
  948         case IMVR_RX_DMERR:             /* receive DMA error */
  949                 dsr = inb (c->RX.DSR);
  950                 if (dsr & (DSR_CHAIN_BOF | DSR_CHAIN_COF)) {
  951                         if (c->call_on_err)
  952                                 c->call_on_err (c, CT_OVERFLOW);
  953                         ++c->ierrs;
  954                         for (i=0; i<NBUF; ++i) {
  955                                 B_LEN (c->rdesc[i]) = DMABUFSZ;
  956                                 B_STATUS (c->rdesc[i]) = 0;
  957                         }
  958                         ct_start_receiver (c, 1, c->rphys[0], DMABUFSZ,
  959                                 c->rdphys[0], c->rdphys[NBUF-1]);
  960                         c->rn = 0;
  961                 }
  962                 /* Clear DMA interrupt. */
  963                 outb (c->RX.DSR, dsr);
  964                 ++c->rintr;
  965                 break;
  966 
  967         case IMVR_TX_DMOK:              /* transmit DMA normal end */
  968         case IMVR_TX_DMERR:             /* transmit DMA error      */
  969                 dsr = inb (c->TX.DSR);
  970                 cda = inw (c->TX.CDA);
  971 
  972                 for (i=0; i<NBUF && cda != (unsigned short)c->tdphys[i]; ++i)
  973                         continue;
  974                 if (i >= NBUF)
  975                         i = 1; /* cannot happen */
  976                 if (dsr & DSR_CHAIN_COF) {
  977                         if (c->call_on_err)
  978                                 c->call_on_err (c, CT_UNDERRUN);
  979                         ++c->oerrs;
  980                 }
  981                 while (c->tn != i) {
  982                         if (c->call_on_tx)
  983                                 c->call_on_tx (c, c->attach[c->tn],
  984                                         B_LEN(c->tdesc[c->tn]));
  985                         ++c->opkts;
  986                         c->obytes += B_LEN(c->tdesc[c->tn]);
  987 
  988                         c->tn = (c->tn + 1) % NBUF;
  989                         /* Clear DMA interrupt. */
  990                         outb (c->TX.DSR, DSR_CHAIN_EOM | DSR_DMA_CONTINUE);
  991                 }
  992                 outb (c->TX.DSR, dsr & ~DSR_CHAIN_EOM);
  993                 ++c->tintr;
  994                 break;
  995 
  996         case IMVR_TX_INT:               /* transmit error, HDLC only */
  997                 st1 = inb (c->ST1);
  998                 if (st1 & ST1_HDLC_UDRN) {
  999                         if (c->call_on_err)
 1000                                 c->call_on_err (c, CT_UNDERRUN);
 1001                         ++c->oerrs;
 1002                 }
 1003                 outb (c->ST1, st1);
 1004                 ++c->tintr;
 1005                 break;
 1006 
 1007         default:
 1008                 /* Unknown interrupt - cannot happen. */
 1009                 break;
 1010         }
 1011 }
 1012 
 1013 int ct_receive_enabled (ct_chan_t *c)
 1014 {
 1015         int st3;
 1016 
 1017         st3 = inb (c->ST3);
 1018         return (st3 & ST3_RX_ENABLED) ? 1 : 0;
 1019 }
 1020 
 1021 int ct_transmit_enabled (ct_chan_t *c)
 1022 {
 1023         int st3;
 1024 
 1025         st3 = inb (c->ST3);
 1026         return (st3 & ST3_TX_ENABLED) ? 1 : 0;
 1027 }
 1028 
 1029 int ct_buf_free (ct_chan_t *c)
 1030 {
 1031         return (NBUF + c->tn - c->te - 1) % NBUF;
 1032 }
 1033 
 1034 int ct_send_packet (ct_chan_t *c, unsigned char *data, int len,
 1035         void *attachment)
 1036 {
 1037         int dsr, ne;
 1038 
 1039         if (len > DMABUFSZ)
 1040                 return -2;
 1041 
 1042         /* Is it really free? */
 1043         ne = (c->te+1) % NBUF;
 1044         if (ne == c->tn)
 1045                 return -1;
 1046 
 1047         /* Set up the tx descriptor. */
 1048         B_LEN (c->tdesc[c->te]) = len;
 1049         B_STATUS (c->tdesc[c->te]) = FST_EOM;
 1050         c->attach[c->te] = attachment;
 1051         if (c->tbuf[c->te] != data)
 1052                 memcpy (c->tbuf[c->te], data, len);
 1053 
 1054         /* Start the transmitter. */
 1055         c->te = ne;
 1056         outw (c->TX.EDA, (unsigned short) c->tdphys[ne]);
 1057         dsr = inb (c->TX.DSR);
 1058         if (! (dsr & DSR_DMA_ENABLE))
 1059                 outb (c->TX.DSR, DSR_DMA_ENABLE);
 1060         return 0;
 1061 }
 1062 
 1063 int scc_write (ct_chan_t *c, unsigned char *d, int len)
 1064 {
 1065         int i, free;
 1066 
 1067         /* determining free place in buffer */
 1068         if (c->scctx_empty)
 1069                 free = SCCBUFSZ;
 1070         else
 1071                 free = (SCCBUFSZ + c->scctx_b - c->scctx_e) % SCCBUFSZ;
 1072 
 1073         if (len > free)
 1074                 return -1;
 1075 
 1076         for (i=0; i<len; i++){
 1077                 c->scctx[c->scctx_e] = d[i];
 1078                 c->scctx_e = (c->scctx_e+1) % SCCBUFSZ;
 1079         }
 1080         if (c->scctx_empty && len) {
 1081                 cte_out2d (c, c->scctx[c->scctx_b]);
 1082                 c->scctx_empty = 0;
 1083         }
 1084         return 0;
 1085 }
 1086 
 1087 int scc_read (ct_chan_t *c, unsigned char *d, int len)
 1088 {
 1089         int i, bytes;
 1090 
 1091         if (c->sccrx_empty)
 1092                 bytes = 0;
 1093         else
 1094                 bytes = (SCCBUFSZ + c->sccrx_e - 1 - c->sccrx_b) %
 1095                                 SCCBUFSZ + 1;
 1096         if (len > bytes)
 1097                 return -1;
 1098 
 1099         for (i=0; i<len; i++){
 1100                 d[i] = c->sccrx[c->sccrx_b];
 1101                 c->sccrx_b = (c->sccrx_b+1) % SCCBUFSZ;
 1102         }
 1103         if (c->sccrx_b==c->sccrx_e)
 1104                 c->sccrx_empty = 1;
 1105         return 0;
 1106 }
 1107 
 1108 int sccrx_check (ct_chan_t *c)
 1109 {
 1110         int bytes;
 1111 
 1112         if (c->sccrx_empty)
 1113                 bytes = 0;
 1114         else
 1115                 bytes = (SCCBUFSZ + c->sccrx_e - 1 - c->sccrx_b) %
 1116                                 SCCBUFSZ + 1;
 1117         return bytes;
 1118 }
 1119 
 1120 int scc_read_byte (ct_chan_t *c)
 1121 {
 1122         unsigned char a;
 1123 
 1124         if (scc_read (c, &a, 1) < 0)
 1125                 return -1;
 1126         return a;
 1127 }
 1128 
 1129 int scc_write_byte (ct_chan_t *c, unsigned char b)
 1130 {
 1131         if (scc_write (c, &b, 1) < 0)
 1132                 return -1;
 1133         return b;
 1134 }
 1135 
 1136 /*
 1137  * Register event processing functions
 1138  */
 1139 void ct_register_transmit (ct_chan_t *c, void (*func) (ct_chan_t*, void*, int))
 1140 {
 1141         c->call_on_tx = func;
 1142 }
 1143 
 1144 void ct_register_receive (ct_chan_t *c, void (*func) (ct_chan_t*, char*, int))
 1145 {
 1146         c->call_on_rx = func;
 1147 }
 1148 
 1149 void ct_register_error (ct_chan_t *c, void (*func) (ct_chan_t*, int))
 1150 {
 1151         c->call_on_err = func;
 1152 }
 1153 
 1154 void ct_register_scc (ct_chan_t *c, void (*func) (ct_chan_t*))
 1155 {
 1156         c->call_on_scc = func;
 1157 }
 1158 
 1159 void ct_register_modem (ct_chan_t *c, void (*func) (ct_chan_t*))
 1160 {
 1161         c->call_on_msig = func;
 1162 }

Cache object: 3802932206999d050ce2a2266f649b75


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