2 * DDK library for Cronyx-Tau adapters.
4 * Copyright (C) 1998-1999 Cronyx Engineering.
5 * Author: Alexander Kvitchenko, <aak@cronyx.ru>
7 * Copyright (C) 1999-2003 Cronyx Engineering.
8 * Author: Roman Kurakin, <rik@cronyx.ru>
10 * This source is derived from
11 * Diagnose utility for Cronyx-Tau adapter:
12 * by Serge Vakulenko, <vak@cronyx.ru>
14 * This software is distributed with NO WARRANTIES, not even the implied
15 * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
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.
21 * Cronyx Id: ctddk.c,v 1.1.2.3 2003/11/14 16:55:36 rik Exp $
23 #include <sys/cdefs.h>
24 __FBSDID("$FreeBSD$");
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>
37 #ifndef CT_DDK_NO_G703
38 #include <dev/ctau/ctaug7fw.h>
42 #include <dev/ctau/ctaue1fw.h>
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);
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
55 int ct_find (port_t *board_ports)
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];
65 int ct_open_board (ct_board_t *b, int num, port_t port, int irq, int dma)
68 const unsigned char *fw;
69 const cr_dat_tst_t *ft;
72 if (num >= NBRD || ! ct_probe_board (port, irq, dma))
75 /* init callback pointers */
76 for (c=b->chan; c<b->chan+NCHAN; ++c) {
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;
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);
96 /* determine which firmware should be loaded */
109 #ifndef CT_DDK_NO_G703
111 fw = ctaug703_fw_data;
112 flen = ctaug703_fw_len;
113 ft = ctaug703_fw_tvec;
119 flen = ctaue1_fw_len;
124 /* Load firmware and set up board */
125 return ct_setup_board (b, fw, flen, ft);
129 * must be called on the exit
131 void ct_close_board (ct_board_t *b)
133 ct_setup_board (b, 0, 0, 0);
135 /* Reset the controller. */
136 outb (BCR0(b->port), 0);
138 /* Disable DMA channel. */
144 static void ct_g703_rate (ct_chan_t *c, unsigned long rate)
147 ct_setup_g703 (c->board);
153 static void ct_chan_baud (ct_chan_t *c, unsigned long baud)
157 c->hopt.txs = CLK_INT;
160 c->hopt.txs = CLK_LINE;
165 void ct_set_baud (ct_chan_t *c, unsigned long baud)
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;
180 ct_chan_baud (c, baud);
184 * Configure Tau/E1 board.
186 static void ct_e1_config (ct_board_t *b, unsigned char cfg)
188 if (cfg == b->opt.cfg)
192 b->chan[1].mode = M_HDLC;
194 b->chan[1].mode = M_E1;
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);
208 * Config Tau/G.703 board
210 static void ct_g703_config (ct_board_t *b, unsigned char cfg)
212 if (cfg == b->opt.cfg)
216 b->chan[1].mode = M_HDLC;
218 b->chan[1].mode = M_G703;
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);
231 int ct_set_clk (ct_chan_t *c, int clk)
234 c->board->opt.clk1 = clk;
236 c->board->opt.clk0 = clk;
237 if (c->mode == M_E1) {
238 ct_setup_e1 (c->board);
240 } if (c->mode == M_G703) {
241 ct_setup_g703 (c->board);
247 int ct_get_clk (ct_chan_t *c)
249 return c->num ? c->board->opt.clk1 : c->board->opt.clk0;
252 int ct_set_ts (ct_chan_t *c, unsigned long ts)
254 if (! (c->mode == M_E1))
257 c->board->opt.s1 = ts;
259 c->board->opt.s0 = ts;
260 ct_setup_e1 (c->board);
264 int ct_set_subchan (ct_board_t *b, unsigned long ts)
266 if (b->chan[0].mode != M_E1)
273 int ct_set_higain (ct_chan_t *c, int on)
275 if (! (c->mode == M_E1))
277 c->gopt.higain = on ? 1 : 0;
278 ct_setup_e1 (c->board);
283 * Start service channel.
285 void ct_start_scc (ct_chan_t *c, char *rxbuf, char *txbuf)
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)
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);
301 * Start HDLC channel.
303 void ct_start_chan (ct_chan_t *c, ct_buf_t *cb, unsigned long phys)
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;
321 c->rdesc = c->tdesc + NBUF;
324 for (i=0; i<NBUF; ++i) {
325 c->rbuf[i] = cb->rbuffer[i];
326 c->tbuf[i] = cb->tbuffer[i];
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);
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;
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;
354 if (c->type & T_E1) {
356 if (c->num && c->board->opt.cfg == CFG_B)
359 if (c->type & T_G703) {
361 if (c->num && c->board->opt.cfg == CFG_B)
366 /* enable receiver */
368 ct_start_receiver (c, 1 , c->rphys[0], DMABUFSZ, c->rdphys[0],
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);
376 /* Enable transmitter */
379 ct_start_transmitter (c, 1 , c->tphys[0], DMABUFSZ, c->tdphys[0],
381 outb (c->TX.DIR, DIR_CHAIN_EOME | DIR_CHAIN_BOFE | DIR_CHAIN_COFE);
383 /* Clear DTR and RTS */
389 * Turn receiver on/off
391 void ct_enable_receive (ct_chan_t *c, int on)
393 unsigned char st3, ier0, ier1;
396 /* enable or disable receiver */
397 if (on && ! (st3 & ST3_RX_ENABLED)) {
399 ct_start_receiver (c, 1 , c->rphys[0], DMABUFSZ, c->rdphys[0],
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);
408 } else if (! on && (st3 & ST3_RX_ENABLED)) {
410 outb (c->CMD, CMD_RX_DISABLE);
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);
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);
426 * Turn transmitter on/off
428 void ct_enable_transmit (ct_chan_t *c, int on)
430 unsigned char st3, ier0, ier1;
433 /* enable or disable receiver */
434 if (on && ! (st3 & ST3_TX_ENABLED)) {
437 ct_start_transmitter (c, 1 , c->tphys[0], DMABUFSZ,
438 c->tdphys[0], c->tdphys[0]);
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);
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);
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);
457 int ct_set_config (ct_board_t *b, int cfg)
459 if (b->opt.cfg == cfg)
467 ct_g703_config (b, cfg);
474 ct_e1_config (b, cfg);
477 return cfg == CFG_A ? 0 : -1;
481 int ct_get_dpll (ct_chan_t *c)
483 return (c->hopt.rxs == CLK_RXS_DPLL_INT);
486 void ct_set_dpll (ct_chan_t *c, int on)
488 if (on && ct_get_baud (c))
489 c->hopt.rxs = CLK_RXS_DPLL_INT;
491 c->hopt.rxs = CLK_LINE;
495 int ct_get_nrzi (ct_chan_t *c)
497 return (c->opt.md2.encod == MD2_ENCOD_NRZI);
501 * Change line encoding to NRZI, default is NRZ
503 void ct_set_nrzi (ct_chan_t *c, int on)
505 c->opt.md2.encod = on ? MD2_ENCOD_NRZI : MD2_ENCOD_NRZ;
506 outb (c->MD2, *(unsigned char*)&c->opt.md2);
510 * Transmit clock inversion
512 void ct_set_invtxc (ct_chan_t *c, int on)
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);
519 int ct_get_invtxc (ct_chan_t *c)
521 return (c->board->bcr2 & (c->num ? BCR2_INVTXC1 : BCR2_INVTXC0)) != 0;
525 * Receive clock inversion
527 void ct_set_invrxc (ct_chan_t *c, int on)
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);
534 int ct_get_invrxc (ct_chan_t *c)
536 return (c->board->bcr2 & (c->num ? BCR2_INVRXC1 : BCR2_INVRXC0)) != 0;
540 * Main interrupt handler
542 void ct_int_handler (ct_board_t *b)
544 unsigned char bsr0, imvr;
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)
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);
564 static void ct_e1_interrupt (ct_board_t *b)
568 sr = inb (E1SR(b->port));
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);
575 static void ct_scc_interrupt (ct_board_t *b)
578 unsigned char ivr, a = AM_A; /* assume channel A */
579 ct_chan_t *c = b->chan;
581 ivr = cte_in2 (b->port, AM_IVR);
583 ++c, a = 0; /* really channel B */
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) {
590 cte_out2c (c, AM_CR | CR_RST_TXINT);
592 cte_out2d (c, c->scctx[c->scctx_b]);
595 case IVR_RXERR: /* receive error */
596 case IVR_RX: /* receive character available */
597 rsr = cte_in2 (b->port, a|AM_RSR);
599 if (rsr & RSR_RXOVRN) { /* rx overrun */
601 c->call_on_err (c, CT_SCC_OVERRUN);
602 } else if (rsr & RSR_FRME) { /* frame error */
604 c->call_on_err (c, CT_SCC_FRAME);
606 c->sccrx[c->sccrx_e] = cte_in2d (c);
607 c->sccrx_e = (c->sccrx_e + 1) % SCCBUFSZ;
611 if (c->sccrx_e == c->sccrx_b && ! c->sccrx_empty)
613 c->call_on_err (c, CT_SCC_OVERFLOW);
616 cte_out2c (c, CR_RST_ERROR);
619 case IVR_STATUS: /* external status interrupt */
620 /* Unexpected SCC status interrupt. */
621 cte_out2c (c, CR_RST_EXTINT);
627 * G.703 mode channel: process 1-second timer interrupts.
628 * Read error and request registers, and fill the status field.
630 void ct_g703_timer (ct_chan_t *c)
632 int bpv, cd, tsterr, tstreq;
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. */
639 if (c->mode != M_G703)
641 if (c->totsec + c->cursec <= 1)
647 bpv = inb (GERR (c->board->port)) & (c->num ? GERR_BPV1 : GERR_BPV0);
648 outb (GERR (c->board->port), bpv);
650 tsterr = inb (GERR (c->board->port)) & (c->num ? GERR_ERR1 : GERR_ERR0);
651 outb (GERR (c->board->port), tsterr);
653 tstreq = inb (GLDR (c->board->port)) &
654 (c->num ? GLDR_LREQ1 : GLDR_LREQ0);
655 outb (GLDR (c->board->port), tstreq);
657 /* Compute the SNMP-compatible channel status. */
659 ++c->currnt.bpv; /* bipolar violation */
661 c->status |= ESTS_LOS; /* loss of signal */
663 c->status |= ESTS_TSTERR; /* test error */
665 c->status |= ESTS_TSTREQ; /* test code detected */
668 c->status = ESTS_NOALARM;
670 /* Unavaiable second -- loss of carrier, or receiving test code. */
671 if ((! cd) || tstreq)
672 /* Unavailable second -- no other counters. */
675 /* Line errored second -- any BPV. */
679 /* Collect data for computing
680 * degraded minutes. */
686 /* Degraded minutes -- having more than 50% error intervals. */
687 if (c->cursec / 60 == 0) {
688 if (c->degerr*2 > c->degsec)
694 /* Rotate statistics every 15 minutes. */
695 if (c->cursec > 15*60) {
699 c->interval[i] = c->interval[i-1];
700 c->interval[0] = c->currnt;
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));
717 c->totsec += c->cursec;
722 static void ct_e1timer_interrupt (ct_chan_t *c)
725 unsigned char sr1, sr2, ssr;
726 unsigned long bpv, fas, crc4, ebit, pcv, oof;
728 port = c->num ? E1CS1(c->board->port) : E1CS0(c->board->port);
730 sr2 = cte_ins (port, DS_SR2, 0xff);
731 /* is it timer interrupt ? */
732 if (! (sr2 & SR2_SEC))
735 /* first interrupts should be ignored */
736 if (c->e1_first_int > 0) {
744 /* Compute the SNMP-compatible channel status. */
745 sr1 = cte_ins (port, DS_SR1, 0xff);
746 ssr = cte_in (port, DS_SSR);
749 if (sr1 & (SR1_RCL | SR1_RLOS))
750 c->status |= ESTS_LOS; /* loss of signal */
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 */
758 c->status |= ESTS_FARLOF; /* far loss of framing */
760 /* Controlled slip second -- any slip event. */
761 if (sr1 & SR1_RSLIP) {
765 if (ssr & SSR_SYNC) {
766 c->status |= ESTS_LOF; /* loss of framing */
767 ++oof; /* out of framing */
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 */
776 c->status = ESTS_NOALARM;
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));
784 c->currnt.bpv += bpv;
785 c->currnt.fse += fas;
787 c->currnt.crce += crc4;
788 c->currnt.rcrce += ebit;
791 /* Path code violation is frame sync error if CRC4 disabled,
792 * or CRC error if CRC4 enabled. */
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. */
803 /* Line errored second -- any BPV. */
807 /* Errored second -- any PCV, or out of frame sync,
808 * or any slip events. */
809 if (pcv || oof || (sr1 & SR1_RSLIP))
812 /* Severely errored framing second -- out of frame sync. */
816 /* Severely errored seconds --
817 * 832 or more PCVs, or 2048 or more BPVs. */
818 if (bpv >= 2048 || pcv >= 832)
821 /* Bursty errored seconds --
822 * no SES and more than 1 PCV. */
826 /* Collect data for computing
827 * degraded minutes. */
829 c->degerr += bpv + pcv;
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)
842 /* Rotate statistics every 15 minutes. */
843 if (c->cursec > 15*60) {
847 c->interval[i] = c->interval[i-1];
848 c->interval[0] = c->currnt;
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;
866 c->totsec += c->cursec;
871 static void ct_hdlc_interrupt (ct_chan_t *c, int imvr)
873 int i, dsr, st1, st2, cda;
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])
883 i = c->rn; /* cannot happen */
885 int cst = B_STATUS (c->rdesc[c->rn]);
886 if (cst == FST_EOM) {
889 c->call_on_rx (c, c->rbuf[c->rn],
890 B_LEN(c->rdesc[c->rn]));
892 c->ibytes += B_LEN(c->rdesc[c->rn]);
893 } else if (cst & ST2_OVRN) {
894 /* Receive overrun error */
896 c->call_on_err (c, CT_OVERRUN);
898 } else if (cst & (ST2_HDLC_RBIT |
899 ST2_HDLC_ABT | ST2_HDLC_SHRT)) {
900 /* Receive frame error */
902 c->call_on_err (c, CT_FRAME);
904 } else if ((cst & ST2_HDLC_EOM)
905 && (cst & ST2_HDLC_CRCE)) {
906 /* Receive CRC error */
908 c->call_on_err (c, CT_CRC);
910 } else if (! (cst & ST2_HDLC_EOM)) {
911 /* Frame dose not fit in the buffer.*/
913 c->call_on_err (c, CT_OVERFLOW);
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;
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);
929 outb (c->RX.DSR, (dsr & 0xfc) | DSR_DMA_ENABLE);
934 case IMVR_RX_INT: /* receive status */
942 /* Clear interrupt. */
948 case IMVR_RX_DMERR: /* receive DMA error */
949 dsr = inb (c->RX.DSR);
950 if (dsr & (DSR_CHAIN_BOF | DSR_CHAIN_COF)) {
952 c->call_on_err (c, CT_OVERFLOW);
954 for (i=0; i<NBUF; ++i) {
955 B_LEN (c->rdesc[i]) = DMABUFSZ;
956 B_STATUS (c->rdesc[i]) = 0;
958 ct_start_receiver (c, 1, c->rphys[0], DMABUFSZ,
959 c->rdphys[0], c->rdphys[NBUF-1]);
962 /* Clear DMA interrupt. */
963 outb (c->RX.DSR, dsr);
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);
972 for (i=0; i<NBUF && cda != (unsigned short)c->tdphys[i]; ++i)
975 i = 1; /* cannot happen */
976 if (dsr & DSR_CHAIN_COF) {
978 c->call_on_err (c, CT_UNDERRUN);
983 c->call_on_tx (c, c->attach[c->tn],
984 B_LEN(c->tdesc[c->tn]));
986 c->obytes += B_LEN(c->tdesc[c->tn]);
988 c->tn = (c->tn + 1) % NBUF;
989 /* Clear DMA interrupt. */
990 outb (c->TX.DSR, DSR_CHAIN_EOM | DSR_DMA_CONTINUE);
992 outb (c->TX.DSR, dsr & ~DSR_CHAIN_EOM);
996 case IMVR_TX_INT: /* transmit error, HDLC only */
998 if (st1 & ST1_HDLC_UDRN) {
1000 c->call_on_err (c, CT_UNDERRUN);
1008 /* Unknown interrupt - cannot happen. */
1013 int ct_receive_enabled (ct_chan_t *c)
1018 return (st3 & ST3_RX_ENABLED) ? 1 : 0;
1021 int ct_transmit_enabled (ct_chan_t *c)
1026 return (st3 & ST3_TX_ENABLED) ? 1 : 0;
1029 int ct_buf_free (ct_chan_t *c)
1031 return (NBUF + c->tn - c->te - 1) % NBUF;
1034 int ct_send_packet (ct_chan_t *c, unsigned char *data, int len,
1042 /* Is it really free? */
1043 ne = (c->te+1) % NBUF;
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);
1054 /* Start the transmitter. */
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);
1063 int scc_write (ct_chan_t *c, unsigned char *d, int len)
1067 /* determining free place in buffer */
1071 free = (SCCBUFSZ + c->scctx_b - c->scctx_e) % SCCBUFSZ;
1076 for (i=0; i<len; i++){
1077 c->scctx[c->scctx_e] = d[i];
1078 c->scctx_e = (c->scctx_e+1) % SCCBUFSZ;
1080 if (c->scctx_empty && len) {
1081 cte_out2d (c, c->scctx[c->scctx_b]);
1087 int scc_read (ct_chan_t *c, unsigned char *d, int len)
1094 bytes = (SCCBUFSZ + c->sccrx_e - 1 - c->sccrx_b) %
1099 for (i=0; i<len; i++){
1100 d[i] = c->sccrx[c->sccrx_b];
1101 c->sccrx_b = (c->sccrx_b+1) % SCCBUFSZ;
1103 if (c->sccrx_b==c->sccrx_e)
1108 int sccrx_check (ct_chan_t *c)
1115 bytes = (SCCBUFSZ + c->sccrx_e - 1 - c->sccrx_b) %
1120 int scc_read_byte (ct_chan_t *c)
1124 if (scc_read (c, &a, 1) < 0)
1129 int scc_write_byte (ct_chan_t *c, unsigned char b)
1131 if (scc_write (c, &b, 1) < 0)
1137 * Register event processing functions
1139 void ct_register_transmit (ct_chan_t *c, void (*func) (ct_chan_t*, void*, int))
1141 c->call_on_tx = func;
1144 void ct_register_receive (ct_chan_t *c, void (*func) (ct_chan_t*, char*, int))
1146 c->call_on_rx = func;
1149 void ct_register_error (ct_chan_t *c, void (*func) (ct_chan_t*, int))
1151 c->call_on_err = func;
1154 void ct_register_scc (ct_chan_t *c, void (*func) (ct_chan_t*))
1156 c->call_on_scc = func;
1159 void ct_register_modem (ct_chan_t *c, void (*func) (ct_chan_t*))
1161 c->call_on_msig = func;